汇编语言笔记-ARM汇编器伪操作


       伪操作:汇编程序中一些特殊指令助记符,作用是完成汇编程序的各种准备工作。伪操作只在源程序进行汇编时被汇编程序处理,不会生成机器码。

符号定义

全局变量定义

       格式:GBLA(GBLL/GBLS) 变量名
       作用:用于定义一个全局变量并进行初始化。
       三条伪操作介绍如下:

伪操作作用
GBLA定义全局的数值变量,并初始化为0
GBLL定义全局的逻辑变量,并初始化为假
GBLS定义全局的字符串变量,并初始化为空

       示例:

  GBLA NUM    ;定义一个全局的数值变量,变量名为NUM
  GBLL LOGIC  ;定义一个全局的逻辑变量,变量名为LOGIC  
  GBLS STRING ;定义一个全局的字符串变量,变量名为STRING 

局部变量定义

       与全局变量定义中的三条指令类似,LCLA、LCLL和LCLS分别用于定义局部的数值变量、逻辑变量及字符串变量,局部的意思在于,此种变量只能在宏中定义:宏MACRO介绍
       示例(这里在MACRO等前面添加了大量空格,但实际上只需要不顶格即可):

        MACRO                        
$label  message $a                   
        LCLS    err                  
                                     
err     SETS    "error no: "         
$label
        INFO    0, "err":CC::STR:$a  
        MEND

变量赋值

       格式:变量名 SETA(SETL/SETS) 相应值
       作用:用于定义一个全局变量并进行初始化。三条伪操作介绍如下:

伪操作作用
SETA为数值变量赋值
SETL为逻辑变量赋值
SETS为字符串变量赋值

       示例:

NUM    SETA 4                ;将数值变量NUM赋值为4
LOGIC  SETL {TRUE}           ;将逻辑变量LOGIC赋值为真(不可改为1)
STRING SETS "nhfgtnhgfdb"    ;将字符串变量STRING赋值为相应字符串

寄存器列表名称定义

       格式:寄存器列表名 RLIST 寄存器列表
       作用:为多个寄存器命名为一个名称以方便使用。
       示例:

reglist RLIST {R5-R8}
  LDMIA R0!,reglist     ;这两句等效于LDMIA R0!,{R5-R8}

数据定义

简单数据定义

       格式:标号 伪操作名 表达式

伪操作作用注意事项
DCB分配一片连续的字节存储单元并初始化表达式可为0 ~ 255的数值或字符串(可以用“=”代替)
DCW(DCWU)分配一片连续的半字存储单元并初始化表达式为程序标号或数值表达式(DCW分配的字存储单元是半字对齐,而DCWU不是)
DCD(DCDU)分配一片连续的字存储单元并初始化表达式为程序标号或数值表达式(DCD分配的字存储单元是字对齐,而DCDU不是)
DCDO分配一片按字对齐的字内存单元,并将每个字单元的内容初始化表达式一般为程序标号,初始化内容为标号相对于R9内容的偏移量
DCI分配一片字对齐(ARM)或半字对齐(Thumb)内存单元并初始化Thumb示例
DCQ(DCQU)分配一片以8字节为单位的连续的存储单元并初始化(DCQ分配的存储单元是字对齐,而DCQU不是)
DCFS( DCFSU)为单精度浮点数分配一片连续的字存储单元并初始化每个单精度浮点数占据1个字单元,DCFS分配的字存储单元是字对齐,而DCFSU不是)
DCFD( DCFDU)为双精度浮点数分配一片连续的字存储单元并初始化每个双精度浮点数占据2个字单元,DCFS分配的字存储单元是字对齐,而DCFSU不是)
SPACE分配一片连续的存储单元并初始化为0表达式为分配的字节数(可以用“%”代替)
NUM_B DCB 11        ;定义变量(标号)NUM_B,并为这个地址赋值为11,即0x0B
      DCB 25        ;为NUM_B+1这个地址赋值为25,即0x19
  ;上两行代码等效于:NUM_B DCB 11,25
  LDR R0, =NUM_B    ;将NUM的地址赋给R0
  LDRB R1, [R0]     ;读出NUM的值(一字节)并赋给R1,此时R1=11
  LDRB R1, [R0,#1]  ;R1=25

NUM_D DCD 11        ;定义变量(标号)NUM_D
      DCD 25
  LDR R0, =NUM_D    ;将NUM的地址赋给R0
  LDRB R1, [R0]     ;读R1=11
  LDRB R1, [R0,#4]  ;R1=25

DCDO操作在验证时,以下代码:NUM DCDO 4出现错误error: A1144E: DCDO directive not supported for non-RWPI format output,未解决,如果有大佬知道怎么用的话求教。

NUM DCI 3,28;DCB 定义一个连续字节内存空间,0是指字符串结束标记,也可以加0dh回车,0ah换行
    DCI 25
  LDR R0, =NUM       ;(应该是因为半字节对齐才导致从-1开始?)
  LDRB R1, [R0,#-1]  ;R1=3
  LDRB R1, [R0,#0]   ;R1=0
  LDRB R1, [R0,#1]   ;R1=28
  LDRB R1, [R0,#2]   ;R1=0
  LDRB R1, [R0,#3]   ;R1=25

特殊结构定义

伪操作语法作用注意事项
MAPMAP 表达式,寄存器定义一个结构化内存表的首地址为表达式+寄存器的值表达式可以是数值或标号,寄存器可为R1 ~ R15,并且可省略,此时首地址为表达式。MAP可用"^"代替
FIELD标号 伪操作名 表达式定义一个结构化内存表的数据域,表达式为当前数据域在内存表中占的字节数FIELD可用"#"代替,内存表示例
LTORGLTORG定义一个数据缓冲池( (literal pool)的开始,防止使用LDR之类指令时数据缓冲区使用越界一般在无条件跳转指令或子程序返回指令之后使用

  MAP 0x10        ;定义结构化内存表首地址为0x10
NUM_1 FIELD 3     ;定义NUM_1的大小为3字节,其地址为0x10
NUM_2 FIELD 6     ;定义NUM_2的大小为6字节,其地址为0x10+3
NUM_3 FIELD 9     ;定义NUM_3的大小为9字节,其地址为0x10+3+6

汇编控制

需要注意的是,下面的伪操作在汇编语言中被视为预编译命令,即if等同于C语言的#if

分支(IF、ELSE、 ENDIF)

  IF 逻辑表达式
    分支语句1
  ELSE
	分支语句2
  ENDIF

循环(WHILE、WEND)

作为预编译命令,WHILE的作用是将一个代码段按照一定格式拷贝N遍,并进行展开

  WHILE 逻辑表达式
循环语句
  WEND

       下面的示例可以用但不建议使用,WHILE在汇编程序中毕竟是预编译命令:

  GBLA count               
count SETA 1    
            
  WHILE count <= 4        
count SETA count+1        
  WEND

宏定义(MACRO、MEND、MEXIT)

       宏定义的编写:

                MACRO                
$label          name    $p1,$p2  ;label为后面调用时使用的名称,name为这个宏的名称,p1、p2为参数,可以为标号,相当于C语言的函数形参
                ; code
$label.loop1                     ; 宏中的标号(可省略)           
                ; code
                BGE $label.loop1 ;进行标号跳转,具体可以不用BGE而是使用B等其它指令
                MEND                  

       宏的调用:宏在被调用时会展开成定义的样子。

自定义的调用名称 name p1,p2   ;name为调用的宏的名称,p1和p2为具体参数名

       示例:

;简单的宏定义
	MACRO
$label MOVing $p1
	MOV R1=$p1
	MEND
;宏调用
GBLA para
aaa MOVing para
;调用后的代码在编译时会被当成:
aaa MOVing para
	MOV R1=para

信息报告

ASSERT

       作用:检查相关条件是否满足,若不满足则报告并终止汇编。
       格式:

  ASSERT 逻辑表达式

       示例:

  GBLA subr1
  GBLA de
  ASSERT  subr1 > de

       像上述示例,相关条件不满足时,在编译时会弹出错误提示:error: A1312E: Assertion failed
       如果满足条件则会正常运行。

INFO

       作用:显示用户自定义的错误信息。当数值表达式为0,将字符串表达式以warning的形式打印,为1时,以error的形式打印。
       格式:

  INFO 数值表达式,字符串表达式

OPT

       作用:改变编译器生成的常规列表文件相应的默认选项。
       格式:

  OPT n

       n的取值范围和效果如下表所示:

n值选项含义
1设置常规列表选项
2关闭常规列表选项
4设置分页符,在新的一页开始显示
8将行号重新设置为0
16设置选项,显示SET、GBL、LCL伪操作
32设置选项,不显示SET、GBL、LCL伪操作
64设置选项,显示展开宏
128设置选项,不显示展开宏
256设置选项,显示宏调用
512设置选项,不显示宏调用
1024设置选项,显示第1遍扫描列表
2048设置选项,不显示第1遍扫描列表
4096设置选项,显示条件汇编伪操作
8192设置选项,不显示条件汇编伪操作
16384设置选项,显示MEND伪操作
32768设置选项,不显示MEND伪操作

TTL和SUBT

       作用:TTL伪操作在列表文件的页顶部显示一个标题。SUBT伪操作在列表文件页标题的下面显示一个子标题。

如果要在列表文件的第一页显示标题或子标题,应将TTL或SUBT放在源程序的第一行。通过TTL或 SUBT改变页标题时,新的标题将在下一页开始起作用。

其它

AREA

       作用:定义代码段、数据段或特定属性的段。其中,段名若以数值开头,则该段名需用"|"括起来,如|1test|。
       格式:

  AREA 段名,属性1,属性2,……

       其中常用属性的有效值及介绍如下表:

有效值作用
CODE定义代码段,默认为READONLY(可以通过添加其它属性进行修改)
DATA定义数据段,默认为READWRITE
READONLY指定本段属性为只读
READWRITE指定本段为可读可写
ALIGN nn的取值范围为0~31,对应的对齐方式为2n,默认按字对齐
COMMON定义一个通用数据段,各个源文件中同名的COMMON段共享一段存储单元,该段不可用于定义代码或数据(变量)

ALIGN

       作用:使代码或数据按一定的边界对齐。
       格式:

  ALIGN [表达式[,偏移量]]

在Cortex-M3、M4内核中,由于使用Thumb汇编,一般会使用ALIGN 4使得代码按4字节对齐

CODE16、CODE32

       作用:指示汇编器将后面的指令解释为16位的Thumb指令或32位的ARM指令。
       格式:

CODE16
CODE32

ENTRY

       作用:指定汇编程序的入口点,每个文件里最多只能有一个,当只有一个时,系统复位后会将该入口作为程序起始点,因此一般在启动文件使用。
       格式:

ENTRY

END

       作用:指示编译器文件结束,一般汇编文件的结尾都会使用
       格式:

END

EQU

       作用:可用于定义常量,类似C语言中的define。
       格式:

名称 EQU 表达式

EXPORT(/GLOBAL)

       作用:声明一个全局的标号,该标号可在其他的文件中引用,可用 GLOBAI代替。
       格式:

  EXPORT 标号{[WEAK]}

{[WEAK]}表示可以在标号后加入[WEAK]选项,声明其他的同名标号优先于该标号被引用,下同。

IMPORT

       作用:指示编译器该标号在其它文件定义,无论后续是否引用该标号,该标号均会被加入到当前源文件的符号表中。
       格式:

  IMPORT 标号{[WEAK]}

EXTERN

       作用:类似IMPORT,但后续未应用则不将其加入到当前源文件的符号表。
       格式::

  EXTERN 标号{[WEAK]}

GET(/INCLUDE)

       作用:将一个源文件(.s)包含到当前的源文件中,并将被包含的源文件在当前位置进行汇编处理。可以使用 INCLUDE代替GET。
       格式:

  GET 文件名

注意汇编语言的包含和C语言包含的区别,C语言进行文件包含是通过include包含.h文件,主要作用是调用其中声明的函数,但这部分功能在汇编程序中通过EXPORT和IMPORT完成,因此汇编程序中通过GET包含文件一般是包含那些将某些宏指令、常量或结构化的数据类型统一放的源文件

INCBIN

       作用:将一个目标文件或数据文件(比如.txt文件)包含到当前的源文件中,被包含的文件不做任何变动地存放在当前文件中,编译器从其后开始继续处理。
       格式:

INCBIN 文件名

RN

       作用:给寄存器定义一个别名,方便记忆该寄存器的功能。
       格式:

名称 RN 表达式

       示例:

Temp RN R0  ;这之后可以通过别名Temp使用寄存器R0

ROUT

       作用:为局部变量定义作用范围,未使用时局部变量的作用范围为所在的整个AREA,使用后局部变量的作用范围为当前ROUT和下一个ROUT之间。
       格式:

局部变量名 ROUT
  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嗨!对于逆向学习汇编语言的学习笔记,我可以给你一些基本的指导。首先,汇编语言是一种低级语言,它与计算机的底层硬件密切相关。逆向工程则是通过分析和理解已编译的程序来获取程序的内部信息。 以下是一些学习汇编语言和逆向工程的建议: 1. 学习基础知识:了解计算机体系结构、寄存器、内存和指令集等基础概念是必要的。可以先阅读相关的书籍或在线教程,掌握这些基本概念。 2. 掌握汇编语言的语法和指令集:每种计算机体系结构都有自己的汇编语言语法和指令集。选择一种你感兴趣的体系结构(如x86、ARM等),并学习它的汇编语言。 3. 练习编写和调试汇编代码:通过编写简单的汇编代码来熟悉语法和指令集。使用调试器来单步执行代码并观察寄存器和内存的变化。 4. 分析已编译程序:选择一个目标程序进行逆向分析。使用反汇编器将程序转换为汇编代码,并分析代码的逻辑和功能。这有助于理解程序的结构和运行过程。 5. 使用调试器进行动态分析:通过调试器来动态地执行程序,并观察程序在运行时的行为。使用断点、内存查看器和寄存器查看器等工具来分析程序的状态和数据。 6. 学习逆向工程工具和技术:了解常用的逆向工程工具和技术,如IDA Pro、OllyDbg、Ghidra等。掌握这些工具的使用可以提高你的逆向分析能力。 7. 参考优秀资源:阅读与逆向工程和汇编语言相关的书籍、论文和博客,关注相关的社区和论坛。与其他逆向工程师交流经验也是很有帮助的。 记住,逆向工程是一个需要耐心和实践的过程。持续学习和实践将帮助你提高逆向分析的技能。祝你在学习汇编语言和逆向工程的过程中取得好成果!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值