汇编语言|常用伪指令(ARM 汇编入门)
发布时间:2026/10/15 21:18:20 锦皓数字建站
`)
前言 汇编语言分为指令语句和伪指令语句。指令语句汇编后生成 CPU 可以直接执行的机器目标代码由 CPU 运行。伪指令语句不会产生任何机器码CPU 不会执行伪指令。伪指令是给汇编器、链接器使用的控制命令用来完成段划分、内存分配、符号别名定义、多文件之间互相调用等编译相关工作。ARM 汇编书写硬性规范CPU 指令助记符例如MOV、ADD、SUB、LDR、STR、BL、BX属于保留关键字绝对不能作为自定义标号就算加上冒号也会编译报错。自定义标号后面必须加冒号:虽然 ARM 汇编语法允许省略冒号但省略后极易把标号误认为指令作业、考试一律书写冒号。CPU 指令、伪指令AREA、ENTRY、EQU、DCD、SPACE等后面不能加冒号。尽量不要使用伪指令名称作为自定义标号部分汇编器虽然可以编译通过但可读性差存在歧义风险。ARM 汇编符号区分大小写。1. EQU 等值赋值伪指令格式标号 EQU 操作数功能给数字或者内存地址定义别名本质是文本替换不占用任何内存单元整个源文件内该标号的值固定不变。;示例1给内存地址0x1000设置别名 AREA_ADDR EQU 1000H ;示例2定义程序使用的数值常量 MAX_NUM EQU 50 MASK EQU 0x0F ;代码中直接使用别名汇编器自动替换成对应数值 MOV R0,#AREA_ADDR ;等价于 MOV R0,#0x1000 MOV R1,#MAX_NUM ;等价于 MOV R1,#502. AREA 段定义伪指令ARM 汇编专属格式AREA 段名,属性1,属性2……功能把程序划分成多个独立模块称为 “段”。有的段存放执行代码有的段存放变量数据同时可以设置段的读写权限、内存对齐、是否初始化。表格属性说明CODE存放 CPU 执行指令默认属性为READONLY只读DATA存放变量与数据默认属性为READWRITE可读可写READONLY内存只允许读取不可修改READWRITE内存可读允许修改写入NOINIT程序启动时该段内存不做初始化ALIGNn内存对齐字节 \(2^n\)例如ALIGN3代表 8 字节对齐;定义只读代码段存放程序指令 AREA CODE_SEG, CODE, READONLY ENTRY START: MOV R0,#0 ;定义可读可写数据段存放运行时会修改的变量 AREA DATA_SEG, DATA, READWRITE DATA_BUF SPACE 1003. ENTRY 程序入口伪指令格式ENTRY功能告诉链接器CPU 上电复位后从此标记位置开始执行程序。注意ENTRY 仅作为标记不生成机器码一个工程至少要有一个ENTRY必须写在CODE代码段内部。AREA MY_CODE,CODE,READONLY ENTRY ;伪指令标记程序入口无冒号 START: MOV R1,#1 ADD R2,R1,#2 END4. ORG 地址定位伪指令51、x86 汇编常用ARM 很少使用格式ORG 绝对地址功能修改汇编位置计数器指定后续代码、数据存放的起始内存地址直到遇见下一条ORG指令地址才会重新改变。ORG 8000H ;下面所有内容从内存0x8000地址开始存放 ADD R1,#1 MOV R2,#2 ORG 0x2000 ;切换存储起始地址后续数据存放在0x2000之后 DATA_BUF1: DB 0x11,0x225. DB / DW 数据定义伪指令DB定义1 字节8bit数据可以存放数字、ASCII 字符。 格式[标号:] DB 字节常数 | 字符 | 表达式DW定义16 位字2 字节数据用法与 DB 完全相同。ORG 8000H DATA1: DB 43H,09H,08H ;连续保存3个1字节数据 DATA2: DB 07H MY_STR: DB A,B,C,0 ;定义ASCII字符串末尾0作为字符串结束标记 WORD_BUF: DW 0x1234,0x5678 ;DW每一项占用2字节内存⚠️注意不要使用STR:作为标号STR是 ARM 存储指令属于保留关键字。6. DCD / DCDU 32 位字分配伪指令ARM 汇编格式标号 DCD / DCDU 表达式列表DCD分配连续 32 位4 字节内存单元严格 4 字节字对齐。DCDU分配 32 位内存单元不强制字对齐。表达式既可以写数字也可以写标号用来保存标号对应的内存地址中断向量表大量使用该伪指令。DATA_TEST: DCD 4,5,6 ;分配3个4字节空间分别存入4、5、6 ;向量表 VECTOR_TABLE: DCD 0x20000000 DCD Reset_Handler ;存储标号Reset_Handler的内存地址 UNALIGN_DATA: DCDU 0x1111,0x22227. SPACE 内存空间分配伪指令格式标号 SPACE 字节数简写符号%等价于 SPACE单位字节功能划出一块连续内存区域分配的内存全部初始化为 0多用于缓冲区、栈空间。DATA_SPACE: SPACE 1000 ;分配1000字节内存全部清零 STACK_BUF: SPACE 256 ;分配256字节栈内存 BUF2: % 64 ;简写写法分配64字节并清零8. PRESERVE8 堆栈 8 字节对齐伪指令ARM 汇编格式PRESERVE8 {FALSE}功能通知链接器当前文件堆栈是否保持 8 字节对齐。汇编语言和 C 语言互相调用时必须开启该伪指令如果不满足 8 字节对齐程序运行会发生异常崩溃。PRESERVE8 ;开启堆栈8字节对齐C与汇编混编必备 ;PRESERVE8 {FALSE} ;关闭堆栈8字节对齐9. EXPORT、EXTRN、IMPORT 多文件模块伪指令应用场景实际项目代码量很大不会把全部代码写在一个汇编文件里。 举例文件A.s写了一个子程序_STARTUP文件B.s需要调用A.s里面已经写好的_STARTUP子程序两个.s文件是独立的单独汇编的时候互相看不到对方内部定义的标号。 需要依靠EXPORT、EXTRN/IMPORT打通多个汇编文件之间的符号访问。EXPORT将本文件的标号对外公开在 A.s 中使用 EXPORT 把内部标号公开其他汇编文件才可以访问调用该标号如果不写 EXPORT标号只在当前文件内部有效外部不可见。文件A.s;A.s完整内容 AREA CODE,CODE,READONLY EXPORT _STARTUP ;对外公开标号_STARTUP允许别的文件访问 _STARTUP: ;A.s内部自定义的子程序入口标号 MOV R0,#0 BX LR ;子程序执行完毕返回调用处EXTRN声明标号来自外部其他文件B.s 想要调用 A.s 的_STARTUP但是 B.s 没有定义_STARTUP。汇编编译 B.s 时汇编器会报 “找不到符号” 错误。使用EXTRN告诉汇编器这个标号不是本文件定义的定义在别的文件等链接阶段再去找真实地址。文件B.s;B.s完整内容 AREA CODE,CODE,READONLY EXTRN _STARTUP:CODE ;声明_STARTUP是外部的代码标号不在本文件定义 ENTRY START: BL _STARTUP ;BL指令调用子程序调用A.s中的_STARTUP MOV R1,#2 END完整工作步骤A.s编写子程序_STARTUP:使用EXPORT _STARTUP对外公开符号。B.s使用EXTRN _STARTUP:CODE声明该标号属于外部。汇编器分别编译 A.s、B.s生成A.o、B.o两个目标文件。链接器把 A.o 与 B.o 合并。链接器发现 B 要调用_STARTUP就到 A.o 里面找到_STARTUP真实内存地址填入 B 的机器码中。IMPORT 外部符号导入ARM 常用IMPORT功能和 EXTRN 接近ARM 汇编更习惯使用 IMPORT。 语法IMPORT 标号 {[WEAK]}[WEAK]弱符号就算整个工程找不到这个标号的定义链接器也不会报错。AREA INIT,CODE,READONLY IMPORT Main ;Main函数写在C语言文件汇编中声明这是外部标号 ENTRY START: B Main ;跳转到C语言的Main函数 IMPORT Err_Handler [WEAK] B Err_Handler10. CODE16 / CODE32 指令集声明伪指令格式CODE16 CODE32CODE32告诉汇编器后续代码编译为 32 位 ARM 指令。CODE16告诉汇编器后续代码编译为 16 位 Thumb 指令。⚠️重要提醒该伪指令仅仅控制汇编器如何编译源代码不能改变 CPU 硬件运行状态真正切换 ARM/Thumb 处理器模式需要使用BX指令。AREA MIX_CODE,CODE,READONLY CODE32 ;后续编译32位ARM指令 ARM_FUNC: MOV R0,#1 CODE16 ;后续编译16位Thumb指令 THUMB_FUNC: MOVS R1,#211. PROC / ENDP 过程子程序伪指令格式子程序名 PROC 指令 RET ENDP功能用来定义汇编子程序PROC标记子程序开始ENDP标记子程序结束二者必须成对出现使用BL指令调用子程序。ADD_SUB PROC ;子程序开始子程序名字ADD_SUB ADD R0,R0,R1 RET ;RET子程序返回 ENDP ;子程序结束 BL ADD_SUB ;调用上面定义好的子程序12. END 源程序结束伪指令格式END功能标记当前这一个汇编源文件编译到此结束。注意一个.s源文件只能写一条 END写在文件的末尾END 之后书写的全部代码汇编器直接忽略不会参与编译。AREA TEST,CODE,READONLY ENTRY START: MOV R0,#1 END ;本汇编源文件到此结束综合完整示例ARM 简易启动框架PRESERVE8 AREA DEMO_CODE,CODE,READONLY EXPORT Reset_Handler IMPORT Main ENTRY Reset_Handler PROC LDR SP,0x20001000 ;设置栈指针 B Main ;跳转到C语言main函数 ENDP AREA DEMO_DATA,DATA,READWRITE BUFF: SPACE 64 ;分配64字节清零缓冲区 CONST_BYTES: DB 0x01,0x02,0x03 END附录标号使用小结✅合法标号示例START:、MY_STR:、DATA_BUF:❌禁止作为标号MOV:、LDR:、STR:CPU 指令属于保留关键字标号可以单独占一行但是冒号不要省略冒号START: MOV R0,#1补充区分51 单片机汇编没有LDR、STR指令所以STR:作为标号是合法ARM32 汇编中 LDR、STR 是硬件指令严禁用作标号两套汇编规则不要混淆。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。