汇编、反汇编和机器码
1、程序处理的4个步骤
(1)我们的第1个LED程序涉及2个文件:start.S、main.c,它们的处理过程如下:
- 编译:将预处理后的代码(
.i文件)翻译成汇编语言代码(.s文件)。 - 汇编:将汇编语言代码(
.s文件)翻译成机器语言,生成目标文件(.o或.obj)。 - 链接:将一个或多个目标文件(
.o)与库函数(如标准库libc)合并,生成最终的可执行文件。

(2)我们想深入理解ARM架构,想深入理解汇编与C,想深入理解栈的作用,想深入理解C语言的实质, 就必须把最终的可执行程序,反汇编后,阅读得到的汇编代码。
-
汇编 汇编文件转换为目标文件(里面是机器码)。
-
反汇编 可执行文件(目标文件,里面是机器码),转换为汇编文件。
2、KEIL下怎么反汇编(了解即可)
在KEIL的User选项中,如下图添加这两项:
fromelf --bin --output=led.bin Objects\led_c.axf
fromelf --text -a -c --output=led.dis Objects\led_c.axf
然后重新编译,即可得到二进制文件led.bin(以后会分析)、反汇编文件led.dis。 如下图操作:

3、GCC下反汇编(了解即可)
使用GCC工具链编译程序时,在Makefile中有这一句:
$(OBJDUMP) -D -m arm led.elf > led.dis # OBJDUMP = arm-linux-gnueabihf-objdump
它就是把可执行程序led.elf,反汇编,得到led.dis。
4、机器码与汇编
(1)参考资料
- DDI0403E_B_armv7m_arm.pdf P254 // cortex M3/M4
- ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf P410 // cortex A7
(2)伪指令是实际不存在的ARM命令,编译器在编译时转换成存在的ARM指令。 我们代码中的ldr r1, =0xxxxxxxx 这条伪指令的真实指令是什么呢? 我们可以通过反汇编来查看。
LDR SP, =(0x20000000+0x10000) // STM32F103
ldr sp, =(0x80000000+0x100000) // IMX6ULL
ldr sp, =0xc0000000 + 0x100000 // STM32MP157 A7
4.1、STM32F103反汇编
我们只摘取前面一小段,第一列是地址,第二列是机器码,第三列是汇编:

4.2、STM32MP157反汇编

4.3、IMX6ULL反汇编

4.4、机器码与汇编示例
4.4.1、Thumb/Thumb2指令集

4.4.2、ARM指令集

4.5、为什么 PC=当前指令地址+4或8?
- CORTEX M3/M4 使用Thumb2指令集,一条指令是16位或32位。
- CORTEX A7 默认使用ARM指令集,一条指令是32位的。
- 指令采用流水线机制:
- 当前执行地址A的指令;
- 同时已经在对下一条指令进行译码;
- 同时已经在读取下下一条指令:PC = A +4 (Thumb/Thumb2指令集)、PC = A + 8 (ARM指令集)。
参考资料:
https://blog.csdn.net/weixin_42727214/article/details/151897527?spm=1011.2415.3001.5331
