系统移植—1.3 GNU汇编

一、综述

  在不同的平台下,或者不同的编译器,汇编语法会有所不同。例如,MDK和IAR的启动文件startup_stm32f10x_hd.s都是不同的,因为它们的编译器不同。汇编语法就有区别。而在ARM下,使用gcc交叉编译器,所有需要GNU汇编语法。GNU汇编语法适用于所有的架构,并不是ARM独享。
  GNU汇编由一系列的语句组成,每一行一条语句,每条语句有如下三个可选部分。

label:instruction @comment

  label,标号,表示地址位置,标号也可以用来表示数据地址。任何以”:“结尾的标识符都会被识别为一个标号。
  instruction:指令,表示汇编指令或伪指令。
  comment:注释。
  例如

add:
	movs r0, #0x12 @设置R0=0x12

  上面是两行汇编语句,第一条语句只有标号:add。第二条语句包含了指令和注释。需要注意的是,ARM语句中可以全部使用大写,也可以全部使用小写,但是不能大小写混用。

二、伪操作、函数

  常见的伪操作有:
  .byte 定义单字节数据,例如.byte 0x12
  .short 定义双字节数据,例如.short 0x1234
  .long 定义4字节数据,例如.long 0x1234 5678
  .equ 赋值语句,例如.equ num, 0x12,表示num=0x12
  .align 数据字节对齐,例如.align 4,表示4字节对齐
  .end 表示源文件结束
  .global 定义全局,例如.global _start
  .section 定义一个段,例如.section .addnum,表示定义了一个.addnum的段
  汇编系统预定义了一些段名:
  .text 代码段
  .data 初始化的数据段
  .bss 未初始化的数据段
  .rodata 只读数据段
  例如

.global _start

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

  汇编也支持函数,如下所示

函数名:
    函数体
    返回语句

  例如

SVC_Handler:
    ldr r0, = SVC_Handler
    bx r0

三、常用汇编指令

1、处理器内部数据传输指令
  常用的指令有三个:mov、mrs和msr。
  如下图所示:
在这里插入图片描述
  mov指令用于将数据从一个寄存器复制到另外一个寄存器,或者将一个立即数传递到寄存器里面。

mov r0, r1   @将寄存器r1中的数据传递给r0,即r0=r1
mov r0, #0x12  @将立即数0x12传递给r0,即r0=0x12

  mrs指令用于将特殊寄存器中的数据传递给通用寄存器,即读特殊寄存器。

mrs r0, cpsr   @将特殊寄存器cpsr里面的数据传递给r0,即r0=cpsr

  msr指令用于将通用寄存器中的数据传递给特殊寄存器。即写特殊寄存器。

msr cpsr,r0    @将r0中的数据复制到cpsr中,即cpsr=r0

2、存储器访问指令
  ARM不能直接访问存储器,存储器的地址,需要通过寄存器来间接的获取。常用的指令有两个,ldr,str。
在这里插入图片描述
  ldr指令用于从存储器加载数据到寄存器rx中,也可以将一个立即数加载到寄存器rx中。

ldr r0, =0x0209c004   @将寄存器地址0x0209c004加载到r0中,即r0=0x0209c004
ldr r1, [r0]          @读取地址0x0209c004中的数据到r1寄存器中,其中offset为0

  str指令用于将数据写入到存储器中。

ldr r0, =0x0209c004   @将寄存器地址0x0209c004加载到r0中,即r0=0x0209c004
ldr r1, =0x20000002   @将r1保存要写入到寄存器的值,即r1=0x200000002
str r1, [r0]          @将r1中的值写入到r0中所保存的地址中

3、压栈、出栈
  在调用函数时,要想让函数返回后继续之前的代码继续运行,需要将处理器状态保存起来,即保存R0-R15的值。等执行完毕后,再恢复R0-R15。保存的操作称为压栈,恢复的操作称为出栈。压栈的指令为push,出栈的指令为pop。他们可以一次性压栈或出栈多个数据。
在这里插入图片描述
  push压栈指令,当前的sp指针指向0x8000 0000,处理器的堆栈是向下增长的。

push {r0~r13,r12}  @将r0~r3和r12压栈

  压栈完成后,如图所示
在这里插入图片描述

push {lr}  @将lr压栈

在这里插入图片描述
  pop出栈指令,

pop {lr}    @恢复lr
pop {r0~r3,r12}  @恢复r0~r3,r12

4、跳转指令
  常用的跳转指令:b、bl、bx等。
在这里插入图片描述
  b指令,最简单的跳转指令,b指令会将pc寄存器的值设置为跳转目标地址,一旦执行,就会立即跳转到指定的目标地址,不会再返回。

_start:
    ldr sp, =0x80200000    @设置sp
    b main                 @跳转到main函数

  bl指令,它会在跳转之前,在lr中保存当前pc寄存器的值,所以可以通过将lr寄存器的值重新加载到pc中来继续从跳转之前的代码出运行。

push {r0, r1}        @保存r0,r1
cps #0x13            @进入svc模式
bl system_irqhandler @加载c语言中中断函数到r2
cps #0x12            @进入irq模式
pop {r0,r1}
str r0, [r1,#0x10]   @中断执行完成

5、算数运算指令
在这里插入图片描述
6、逻辑运算指令
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值