一、汇编语言和本地代码
计算机CPU只能运行本地代码(机器语言)程序,用C语言等高级语言编写的代码,需要经过编译器编译后,转换为本地代码才能够被CPU解释执行
但是本地代码的可读性非常差,所以需要使用一种能够直接读懂的语言来替换本地代码,那就是在各本地代码中,附带上表示其功能的英文缩写,比如在加法运算的本地代码加上 add(addition)的缩写、在比较运算符的本地代码中加上 cmp(compare)的缩写等,这些通过缩写来表示具体本地代码指令的标志称为 助记符,使用助记符的语言称为 汇编语言。这样,通过阅读汇编语言,也能够了解本地代码的含义了
不过,即使是使用汇编语言编写的源代码,最终也必须要转换为本地代码才能够运行,负责做这项工作的程序称为 编译器,转换的这个过程称为 汇编。在将源代码转换为本地代码这个功能方面,汇编器和编译器是同样的
用汇编语言编写的源代码和本地代码是一一对应的。因而,本地代码也可以反过来转换成汇编语言编写的代码。把本地代码转换为汇编代码的这一过程称为 反汇编,执行反汇编的程序称为 反汇编程序
本地代码和汇编语言一对一的转换:
哪怕是C语言编写的源代码,编译后也会转换成特定的CPU用的本地代码。而将其反汇编的话,就可以得到汇编语言的源代码,并对其内容进行调查。不过,本地代码变成C语言源代码的反编译,要比本地代码转换成汇编代码的反汇编要困难,这是因为,C语言代码和本地代码不是一一对应的关系
二、通过编译器输出汇编语言的源代码
本地代码可以经过反汇编转换成为汇编代码,但是只有这一种转换方式吗?显然不是,C语言编写的源代码也能够通过编译器编译称为汇编代码,下面可以进行尝试一下
首先需要先做一些准备,需要先下载 Borland C++5. 5 编译器,为了方便,我这边直接下载好了读者直接从我的百度网盘提取即可(链接:https://pan.baidu.com/s/19LqVICpn5GcV88thD2AnIA密码:hz1u)
下载完毕,需要进行配置,下面是配置说明(https://wenku.baidu.com/view/22e2f418650e52ea551898ad.html),教程很完整跟着配置就可以,下面开始我们的编译过程
首先用 Windows 记事本等文本编辑器编写如下代码
// 返回两个参数之和的函数 int AddNum(int a,int b){ return a + b; } // 调用AddNum 函数的函数 void MyFunc(){ int c; c = AddNum(123,456); }
编写完成后将其文件名保存为Sample4.c,C语言源文件的扩展名,通常用.c来表示,上面程序是提供两个输入参数并返回它们之和。
在Windows 操作系统下打开 命令提示符,切换到保存Sample4.c的文件夹下,然后在命令提示符中输入
bcc32-c-S Sample4.c
bcc32 是启动 Borland C++的命令,-c 的选项是指仅进行编译而不进行链接,-S选项被用来指定生成汇编语言的源代码
作为编译的结果,当前目录下会生成一个名为 Sample4.asm 的汇编语言源代码。汇编语言源文件的扩展名,通常用.asm来表示,下面就让我们用编辑器打开看一下 Sample4.asm中的内容:
.386p ifdef ??verdion if ??version GT 500H .mmx endif endif model flat ifndef ??version ?debug macro endm endif ?debug S "Sample4.c" ?debug T "Sample4.c" _TEXT segment dword public use32 'CODE' _TEXT ends _DATA segment dword public use32 'DATA' _DATA ends _BSS segment dword public use32 'BSS' _BSS ends DGROUP group _BSS,_DATA _TEXT segment dword public use32 'CODE' _ADDNUM proc near ?livel1@0: ; ; int AddNum(int a,int b){ ; push ebp mov ebp,esp ; ; ; return a + b; ; @1: mov eax,dword ptr [ebp+8] add eax,dword ptr [ebp+12] ; ; ; ; @3: @2: pop ebp ret _AddNum endp _MyFunc proc near ?livel@48: ; ; void MyFunc(){ ; push ebp mov ebp,esp ; ; int c; ; c = AddNum(123,456); ; @4: push 456 push 123 call _AddNum add esp,8 ; ; } ; @5: pop dep ret _MyFunc endp _TEXT ends public _AddNum public _MyFunc ?debug D "Sample4.c" 20343 45835 end
这样编译器就能成功把C语言转换成汇编代码了