退隐猫九_ 发表于 2025-7-20 15:38

2、【52HB逆向】初识编译器

本帖最后由 退隐猫九_ 于 2025-7-20 15:39 编辑

## 编译器

源代码就是我们能理解的高级语言,CPU只会说二进制语言,编译器就是一个翻译官,阅读你的信息,准确无误的翻译给CPU

翻译过程,大概分为:

- 编译:比如cl.exe,读取源代码1.c,检查语法错误,编译成obj目标文件,已经包含了大部分的机器码,但是不完整
- 链接:比如用到printf等,具体实现在库文件,连接器把obj文件和所要用到的支持装订到一起,形成一个exe

下载个Visual Studio的命令行工具或者Visual Studio的Pro专业版,看自己

Developer Command Prompt for VS,打开这个

cd切换到代码目录下,就随便写一个代码

```c
#include <stdio.h>

int main()
{
    printf("Hello World!");
    return 0;
}
```

输入:`cl 1.c`

生成了obj和exe,exe文件此时是可以执行的了

gcc可以看的更明确
gcc -c 1.c,只编译,不链接
gcc 1.o -o mypro,只链接,不编译

## Make/Makefile

若后期我们写了个大项目,很多个.c组成,总不能告诉其他人,先编译a,再编译c,再编译b吧,效率低且易错

make,自动化构建工具,makefile,详细的说明书,多条规则组成,每条告诉make三件事

```makefile
目标 (Target): 依赖(Prerequisites)
                命令(Commands)
```

目标就是想要生成的文件,比如1.exe,依赖需要什么,比如1.o,命令就是都全了,要如何,比如gcc 1.o -o 1.exe

make执行的时候,读取MakeFIle,然后找到目标,检查是否存在,存在就比较和依赖的修改时间,依赖比目标文件旧说明最新,若有一个依赖比目标新,就要开始升成

!(data/attachment/forum/202507/20/153941t9ujuwzxxhzx1ylx.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

新建如上文件,然后创建makefile

```makefile
# 定义最终目标程序名
TARGET = my_app
# 定义编译器
CC = gcc
# 定义编译参数
CFLAGS = -Wall -g

# 默认目标:当直接运行make时,会执行这个规则
all: $(TARGET)
# 链接规则:如何从.o文件生成最终程序
$(TARGET): 1.o utils.o
        $(CC) $(CFLAGS) 1.o utils.o -o $(TARGET)

# 编译规则:如何从.c文件生成.o文件
1.o: 1.c utils.h
        $(CC) $(CFLAGS) -c 1.c

utils.o: utils.c utils.h
        $(CC) $(CFLAGS) -c utils.c

# 清理规则:用于删除所有生成的文件
clean:
        rm -f *.o $(TARGET)
```

## GDB调试

没有一次性完美的事情,还需要调试,GDB就是经典的命令行调试器

修改代码,故意调出错误

```c
#include "utils.h"
#include <stdio.h>

int main()
{
    int a = 10;
    int b = 0;
    int c = a / b;

    printf("The result is: %d\n", c);
    say_hello();
    return 0;
}
```

make clean先清理,再make生成,makefile里的-g就是生成调试符号

然后gdb ./my_app.exe开始调试

- b main,入口设置断点
- r,运行程序,停在了第一行
- n,下一行
- p,打印变量,比如 p a
- q,退出

!(data/attachment/forum/202507/20/153954kzh4pqfb87ft8w4h.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

最后看到报错,算数异常
页: [1]
查看完整版本: 2、【52HB逆向】初识编译器