首先解释一下,由于汇编代码中会存在一些伪指令等内容,所以,写出来的汇编代码,并不一定是真正可以执行的代码,这些类似于伪指令的汇编代码,经过汇编器,转换或翻译成真正的可以执行的汇编指令。所以,上面才会有将“汇编源代码”转换为“真正的汇编代码”这一说。
然后,此处对于有些人不是很熟悉的,如何查看源代码真正对应的汇编代码。
此处,对于汇编代码,有两种:
- 一种是只是进过编译阶段,生成了对应的汇编代码
- 另外一种是,编译后的汇编代码,经过链接器链接后,对应的汇编代码。
总的来说,两者区别很小,后者主要是更新了外部函数的地址等等,对于汇编代码本身,至少对于我们一般所去查看源代码所对应的汇编来说,两者可以视为没区别。
在查看源代码所对应的真正的汇编代码之前,先要做一些相关准备工作:
- 编译uboot
在Linux下,一般编译uboot的方法是:
make distclean
去清除之前配置,编译等生成的一些文件。
make EmbedSky_config
去配置我们的uboot
make
去执行编译
- 查看源码所对应的汇编代码
对于我们此处的uboot的start.S来说:
- 对于编译所生成的汇编的查看方式是
用交叉编译器的dump工具去将汇编代码都导出来:
arm-linux-objdump –d cpu/arm920t/start.o > uboot_start.o_dump_result.txt
这样就把start.o中的汇编代码导出到uboot_start.o_dump_result.txt中了。
然后查看uboot_start.o_dump_result.txt,即可找到对应的汇编代码。
举例来说,对于start.S中的汇编代码:
/* Set up the stack */ stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif sub sp, r0, #12 /* leave 3 words for abort-stack */ bl clock_init
去uboot_start.o_dump_result.txt中,搜索stack_setup,即可找到对应部分的汇编代码:
00000090 <stack_setup>: 90: e51f0058 ldr r0, [pc, #-88] ; 40 <_TEXT_BASE> 94: e2400701 sub r0, r0, #262144 ; 0x40000 98: e2400080 sub r0, r0, #128 ; 0x80 9c: e240d00c sub sp, r0, #12 ; 0xc a0: ebfffffe bl 0 <clock_init>
- 对于链接所生成的汇编的查看方式是
和上面方法一样,即:
arm-linux-objdump –d u-boot > whole_uboot_dump_result.txt
然后打开该txt,找到stack_setup部分的代码:
33d00090 <stack_setup>: 33d00090: e51f0058 ldr r0, [pc, #-88] ; 33d00040 <_TEXT_BASE> 33d00094: e2400701 sub r0, r0, #262144 ; 0x40000 33d00098: e2400080 sub r0, r0, #128 ; 0x80 33d0009c: e240d00c sub sp, r0, #12 ; 0xc 33d000a0: eb000242 bl 33d009b0 <clock_init>
两者不一样地方在于,我们uboot设置了text_base,即代码段的基地址,上面编译后的汇编代码,经过链接后,更新了对应的基地址,所以看起来,所以代码对应的地址,都变了,但是具体地址中的汇编代码,除了个别调用函数的地址和跳转到某个标号的地址之外,其他都还是一样的。
- 对于编译所生成的汇编的查看方式是
对于C语言的源码,也是同样的方法,用对应的dump工具,去从该C语言的.o文件中,dump出来汇编代码。
注意 | |
---|---|
【总结】 不论是C语言还是汇编语言的源文件,想要查看其对应的生成的汇编代码的话,方法很简单,就是用dump工具,从对应的.o目标文件中,导出对应的汇编代码,即可。 |