第 3 章 相关知识点详解

目录

3.1. 如何查看C或汇编的源代码所对应的真正的汇编代码
3.2. uboot初始化中,为何要设置CPU为SVC模式而不是设置为其他模式
3.3. 什么是watchdog + 为何在要系统初始化的时候关闭watchdog
3.3.1. 什么是watchdog
3.3.2. 为何在要系统初始化的时候关闭watchdog
3.4. 为何ARM7中PC=PC+8
3.4.1. 为何ARM9和ARM7一样,也是PC=PC+8
3.5. AMR寄存器的别名 + APCS
3.5.1. ARM中的寄存器的别名
3.5.2. 什么是APCS
3.6. 为何C语言(的函数调用)需要堆栈,而汇编语言却不需要堆栈
3.6.1. 保存现场/上下文
3.6.1.1. 什么叫做上下文context
3.6.2. 传递参数
3.6.3. 举例分析C语言函数调用是如何使用堆栈的
3.7. 关于为何不直接用mov指令,而非要用adr伪指令
3.8. mov指令的操作数的取值范围到底是多少
3.9. 汇编学习总结记录
3.9.1. 汇编中的标号=C中的标号
3.9.2. 汇编中的跳转指令=C中的goto
3.9.3. 汇编中的.globl=C语言中的extern
3.9.4. 汇编中用bl指令和mov pc,lr来实现子函数调用和返回
3.9.5. 汇编中的对应位置有存储值的标号 = C语言中的指针变量
3.9.6. 汇编中的ldr+标号,来实现C中的函数调用
3.9.7. 汇编中设置某个寄存器的值或给某个地址赋值

摘要

3.1. 如何查看C或汇编的源代码所对应的真正的汇编代码

首先解释一下,由于汇编代码中会存在一些伪指令等内容,所以,写出来的汇编代码,并不一定是真正可以执行的代码,这些类似于伪指令的汇编代码,经过汇编器,转换或翻译成真正的可以执行的汇编指令。所以,上面才会有将“汇编源代码”转换为“真正的汇编代码”这一说。

然后,此处对于有些人不是很熟悉的,如何查看源代码真正对应的汇编代码。

此处,对于汇编代码,有两种:

  1. 一种是只是进过编译阶段,生成了对应的汇编代码
  2. 另外一种是,编译后的汇编代码,经过链接器链接后,对应的汇编代码。

总的来说,两者区别很小,后者主要是更新了外部函数的地址等等,对于汇编代码本身,至少对于我们一般所去查看源代码所对应的汇编来说,两者可以视为没区别。

在查看源代码所对应的真正的汇编代码之前,先要做一些相关准备工作:

  1. 编译uboot

    在Linux下,一般编译uboot的方法是:

    1. make distclean

      去清除之前配置,编译等生成的一些文件。

    2. make EmbedSky_config

      去配置我们的uboot

    3. make

      去执行编译

  2. 查看源码所对应的汇编代码

    对于我们此处的uboot的start.S来说:

    1. 对于编译所生成的汇编的查看方式是

      用交叉编译器的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>
                          
    2. 对于链接所生成的汇编的查看方式是

      和上面方法一样,即:

      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目标文件中,导出对应的汇编代码,即可。