新闻中心

EEPW首页>嵌入式系统>设计应用> ARM汇编常用伪操作总结

ARM汇编常用伪操作总结

作者: 时间:2016-11-29 来源:网络 收藏

  首先使用 MACRO 和 MEND 等伪操作定义宏。包含在 MACRO 和 MEND 之间的代码段称为宏定义体,在 MACRO 伪操作之后的一行声明宏的原型(包含宏名、所需的参数),然后就可以在汇编程序中通过宏名来调用它。在源程序被汇编时,汇编器将宏调用展开,用宏定义体代替源程序中的宏定义的名称,并用实际参数值代替宏定义时的形式参数。

本文引用地址://m.amcfsurvey.com/article/201611/340834.htm

  宏定义中的 $label 是一个可选参数。当宏定义体中用到多个标号时,可以使用类似 $label.$internallabel 的标号命名规则使程序易读。

  MACRO 、 MEND 伪操作可以嵌套使用。

  使用示例:

  MACRO

  $HandlerLabel HANDLER $HandleLabel ; 宏的名称为 HANDLER ,有 1 个参数 $HandleLabel

  $HandlerLabel

  sub sp,sp,#4 ;decrement sp(to store jump address)

  stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)

  ldr r0,=$HandleLabel ;load the address of HandleXXX to r0

  ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX

  str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack

  ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)

  MEND

  ;在程序中调用该宏

  HandlerFIQ HANDLER HandleFIQ ;通过宏的名称 HANDLER 调用宏,其中宏的标号为 HandlerFIQ ,参数为 HandleFIQ

  HandlerIRQ HANDLER HandleIRQ

  HandlerUndef HANDLER HandleUndef

  HandlerSWI HANDLER HandleSWI

  HandlerDabort HANDLER HandleDabort

  HandlerPabort HANDLER HandlePabort

  ;程序被汇编后,宏展开的结果

  HandlerFIQ

  sub sp,sp,#4

  stmfd sp!,{r0}

  ldr r0,=HandleFIQ

  ldr r0,[r0]

  str r0,[sp,#4]

  ldmfd sp!,{r0,pc}

  IF 、 ELSE 、 ENDIF

  语法格式:

  IF 逻辑表达式

  指令序列 1

  ELSE

  指令序列 2

  ENDIF

  IF 、 ELSE 、 ENDIF 伪操作能根据条件把一段源代码包括在汇编程序内或者将其排除在程序之外。 [ 是 IF 伪操作的同义词, | 是 ELSE 伪操作的同义词, ] 是 ENDIF 伪操作的同义词。

  IF 、 ELSE 、 ENDIF 伪指令可以嵌套使用。

  使用示例:

  MACRO

  MOV_PC_LR

  [ THUMBCODE

  bx lr

  |

  mov pc,lr

  ]

  内存操作

  DCD “ & ”(或 DCDU )

  语法格式:

  标号 DCD ( 或 DCDU) 表达式

  用于分配一段字内存单元并用伪操作中指定的表达式初始化 。其中,表达式可以为程序中的标号或数字表达式。

  用 DCD 分配的字存储单元是字对齐 的,而用 DCDU 分配的字存储单元并不严格字对齐。

  使用示例:

  DataTest DCD 4,5,6 ; 其值分别为 4 , 5 和 6 。

  data2 DCD memaddr+4 ; 分配一个字单元,其值为程序中标号 memaddr 加 4 个字节

  MAP ( “ ^ ” )

  语法格式:

  MAP 表达式 { ,基址寄存器 }

  用于定义一个结构化的内存表的首地址 。

  表达式可以为程序中的标号或数字表达式,基址寄存器为可选项,当基址寄存器选项不存在时,表达式的值即为内存表的首地址,当该选项存在时,内存表的首地址为表达式的值与基址寄存器的和。

  MAP 伪操作通常与 FIELD 伪操作配合使用来定义结构化的内存表。

  使用示例:

  MAP 0x100 , R9 ; 定义结构化内存表首地址的值为 0x100 + R9 。

  FILED ( “ # ” )

  语法格式:

  标号 FIELD 表达式

  用于定义一个结构化内存表中的数据域 。

  表达式的值为当前数据域在内存表中所占的字节数。

  FIELD 伪操作常与 MAP 伪操作配合使用来定义结构化的内存表结构。 MAP 伪操作定义内存表的首地址, FIELD 伪操作定义内存表中的各数据域的字节长度,并可以为每个数据域指定一个标号供其他的指令引用。

  注意 MAP 和 FIELD 伪操作仅用于定义数据结构,并不实际分配存储单元。

  示例 1 :

  下面的伪操作序列定义一个内存表,其首地址为固定地址 4096 ,该内存表中包括 5 个数据域: consta 长度为 4 个字节; constb 长度为 4 个字节; x 长度为 8 个字节; y 长度为 8 个字节; string 长度为 256 个字节。这种内存表称为基于绝对地址的内存表。

  MAP 4096 ;内存表的首地址为 4096 ( 0x1000 )

  consta FIELD 4 ; consta 长度为 4 个字节,相对位置为 0

  constb FIELD 4 ; constb 长度为 4 个字节,相对位置为 5000

  constb FIELD 4 ; constb 长度为 4 个字节,相对位置为 5000

  x FIELD 8 ; x 长度为 4 个字节,相对位置为 5004

  y FIELD 8 ; y 长度为 4 个字节,相对位置为 5012

  string FIELD 256 ; string 长度为 256 字节,相对位置为 5020

  ; 在指令中可以这样引用内存表中的数据域:

  LDR R6 , consta

  上面的指令仅仅可以访问 LDR 指令前面(或后面) 4KB 地址范围的数据域

  示例 2 :

  下面的伪操作序列定义一个内存表,其首地址为 0 ,该内存表中包括 5 个数据域: consta 长度为 4 个字节; constb 长度为 4 个字节; x 长度为 8 个字节; y 长度为 8 个字节; string 长度为 256 个字节。这种内存表称为基于相对地址的内存表。

  MAP 4096 ;内存表的首地址为 0

  consta FIELD 4 ; consta 长度为 4 个字节,相对位置为 0

  constb FIELD 4 ; constb 长度为 4 个字节,相对位置为 4

  x FIELD 8 ; x 长度为 4 个字节,相对位置为 8

  y FIELD 8 ; y 长度为 4 个字节,相对位置为 16

  string FIELD 256 ; string 长度为 256 字节,相对位置为 24

  ; 可以通过下面的指令方便地访问地址范围超过 4KB 的数据

  MOV R9 , #4096

  LDR R5 , [R9,constb] ;将内存表中数据域 constb 读取到 R5 中

  在这里,内存表中各数据域的实际内存地址不是基于一个固定地址,而是基于 LDR 指令执行时 R9 寄存器中的内容。这样通过上面方法定义的内存表结构可以在程序中有多个实例(通过在 LDR 指令中指定不同的基址寄存器值来实现)。通常用 R9 作为静态基址寄存器。


上一页 1 2 下一页

关键词:ARM

评论


相关推荐

技术专区

关闭