This is my study note of compilation.

GNU汇编语法

编译器不同会导致汇编的语法存在一些区别,这次主要是记录GNU语法的汇编

语句组成

1
2
3
4
5
6
lable表示标签,command则是要执行的操作,@表示注释
lable:
command @ 注释内容
例:
add:
MOVS R0, #0x12 @ 设置R0=0x12
  • 任何以”:”结尾的标识符都会被识别为一个标号
  • ARM中指令、伪指令、伪操作、寄存器名等都可以全部使用大写或全部使用小写,但是不可以大小写混用

定义段

1
.section .testsection @定义一个testsection段
  • 每个段以段名开始,以下一个段名或文件末尾结束
段名 含义
.text 表示代码段
.data 初始化数据段
.bss 未初始化的数据段
.rodata 只读数据段

默认入口标号:_start

1
2
3
.global _start
_start:
ldr r0, =0x12 @r0=0x12
  • 汇编程序默认入口为_start
  • 可以在链接脚本中使用ENTRY来指明其他的入口点

伪操作

伪操作 含义
.byte 定义单字节数据,比如.byte 0x12。
.short 定义双字节数据,比如.short 0x1234。
.long 定义一个 4 字节数据,比如.long 0x12345678。
.equ 赋值语句,格式为:.equ 变量名,表达式,比如.equ num, 0x12,表示 num=0x12。
.align 数据字节对齐,比如:.align 4 表示 4 字节对齐。
.end 表示源文件结束。
.global 定义一个全局符号,格式为:.global symbol,比如:.global _start。

定义函数

1
2
3
4
5
6
7
8
函数名:
函数体
返回语句

例子:
undefined_Handler:
ldr r0, =undefined_Handler
bx r0
  • undefined_Handler:为函数名
  • ldr r0, =undefined_Handler为函数题
  • bx r0 为返回语句,返回语句不是必须的

内部数据传输

  • MOV指令 将寄存器拷贝到另一个寄存器
    1
    2
    MOV R0, R1     @将寄存器R1中的数据传递给R0,R0=R1
    MOV R0, #0x12 @将立即数0x12传递给R0寄存器,R0=0x12
  • MRS指令
    MRS指令用于特殊寄存器数据复制给通用寄存器
    1
    MRS R0, CPSR     @将特殊寄存器CPSR里面的数据传递给R0,即R0=CPSR
  • MSR指令
    MSR指令用于普通寄存器传递给特殊寄存器
    1
    MSR CPSR, R0     @将R0的数据复制到特殊寄存器CPSR中

存储器访问指令

  • LDR指令
    主要用于将存储数据加载到寄存器Rx中,也可以传入立即数。
    1
    2
    LDR R0, =0X0209C004   @将寄存器地址0X0209C005加载到R0中
    LDR R1, [R0] @读取地址0X0209C005中的数据到R1中
  • STR指令
    1
    STR R1, [R0]          @将R1中的值写到R0中所保存的地址中 
    LDR和STR都是按照字进行读取和写入的(32位),如果想要进行半字节的操作,指令为LDRH、STRH

压栈和出栈指令

  • PUSH压栈
    1
    PUSH {R0~R3, R12}     @将R0~R3和R12压栈
  • POP出栈
    1
    POP {R0~R3, R12}              @恢复LRR0~R3和R12
    POP和PUSH的另一种写法是STMFD和LDMFD

跳转指令

  • B指令
    1
    B指令会将PC寄存器的值设置为跳转目标地址,一旦执行则会跳转到目标地址,但是不会返回原处。
  • BL指令
    1
    在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值,所以可以通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行.

运算符指令

指令 计算公式 备注
ADD Rd, Rn, Rm Rd = Rn + Rm 加法运算,指令为 ADD
ADD Rd, Rn, #immed Rd = Rn + #immed 加法运算,指令为 ADD
ADC Rd, Rn, Rm Rd = Rn + Rm + 进位 带进位的加法运算,指令为 ADC
ADC Rd, Rn, #immed Rd = Rn + #immed +进位 带进位的加法运算,指令为 ADC
SUB Rd, Rn, Rm Rd = Rn – Rm 减法
SUB Rd, #immed Rd = Rd - #immed 减法
SUB Rd, Rn, #immed Rd = Rn - #immed 减法
SBC Rd, Rn, #immed Rd = Rn - #immed – 借位 带借位的减法
SBC Rd, Rn ,Rm Rd = Rn – Rm – 借位 带借位的减法
MUL Rd, Rn, Rm Rd = Rn * Rm 乘法(32 位)
UDIV Rd, Rn, Rm Rd = Rn / Rm 无符号除法
SDIV Rd, Rn, Rm Rd = Rn / Rm 有符号除法

逻辑运算指令

  • AND 与
  • ORR 或
  • BIC 位清除
  • ORN 按位或非
  • EOR 按位易或