为什么需要汇编?

  • C语言中的函数调用涉及到出栈入栈,出栈入栈就要 对堆栈进行操作,所谓的堆栈其实就是一段内存,这段内存比较特殊,由SP指针访问, SP指 针指向栈顶。芯片一上电SP指针还没有初始化,所以 C语言没法运行。
  • 对于有些芯片还需要 初始化 DDR,因为芯片本身没有 RAM,或者内部 RAM不开放给用户使用,用户代码需要在 DDR中运行,因此一开始要用汇编来初始化 DDR控制器。

总而言之,我们需要在芯片上电以后用汇 编来初始化一些外设,已完成C语言运行的要求,不会涉及到复杂的代码。

GNU汇编语法

我们编译ARM架构的代码,都是在Linux上使用gcc交叉编译器,所以使用的ARM汇编也是符合GNU汇编的语法要求的。

指令语句

GNU每行一个语句,语句格式为:label: instruction @ comment

  • label:标号,表示指令的地址,也可以表示数据地址
  • instruction:汇编指令或伪指令。指令可以大写或小写
  • @comment:@表示注释内容,也可以使用/**/来注释

    指令段

    每个指令段以段名开始,以下一段名或文件结尾为结束,格式为:.section .name

  • .section:伪操作关键字

  • .name:可以是自定义的段名,也可以是下面预定义的:
    • .data 初始化的数据段
    • .bss 未初始化的数据段
    • .rodata 只读数据段

      汇编入口

      汇编程序的默认入口标号是 _start,不过也可以在链接脚本中使用 ENTRY来指明其它的入口点。
      下面的代码就是使用 _start作为入口标号: ```basic .global _start

_start: ldr r0, =0x12 @r0=0x12

  1. <a name="B7Nuh"></a>
  2. ## 伪操作
  3. 常见的伪操作有:
  4. - .byte 定义单字节数据,比如 .byte 0x12。
  5. - .short 定义双字节数据,比如 .short 0x1234。
  6. - .long 定义一个 4字节数据,比如 .long 0x12345678。
  7. - .equ 赋值语句,格式为: :.equ 变量名,表达式,比如 .equ num, 0x12,表示 num=0x12。
  8. - .align 数据字节对齐,比如: :.align 4表示 4字节对齐。
  9. - .end 表示源文件结束。
  10. - .global 定义一个全局符号,格式为: :.global symbol,比如 :.global _start
  11. <a name="8vQnW"></a>
  12. ## 汇编函数
  13. 定义函数的格式如下,其中返回语句不是必须的:

函数名 : 函数体 返回语句 ```