尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

微机原理与接口技术 · 第4章《汇编语言及其程序设计》知识点

微机原理与接口技术 · 第4章《汇编语言及其程序设计》知识点 微机原理与接口技术 · 第4章《汇编语言及其程序设计》知识点梳理本文整理自福州大学吴衔誉教授《微机原理与接口技术》第四章课件系统讲解汇编语言简介、指令分类与条件域、寻址方式、Cortex-M3 指令集数据传送 / 数据处理 / 跳转 / 其他以及汇编程序设计五大板块。目录一、汇编语言简介二、指令分类、条件域和指令格式三、寻址方式四、Cortex-M3 指令集五、汇编程序设计本章小结与思考题一、汇编语言简介1.1 三种层次的计算机语言语言特点优点缺点机器语言二进制代码CPU 唯一直接识别执行直接执行、速度快、资源占用少可读性/可移植差、编程繁杂汇编语言助记符书写地址/数据可用符号表示编写/阅读/修改方便、不易出错须「翻译」成机器语言才能执行高级语言C/C、Java接近英语不需了解硬件结构易读写、结构简洁须「编译」成机器语言指令与程序指令是计算机能识别执行的操作命令指令的集合叫指令系统不同 CPU 不同同一指令系统的同一条指令有汇编指令与机器指令两种形式。把汇编翻译成机器语言叫汇编assemble反方向叫反汇编。1.2 助记符与指令格式操作码用缩写英文字母助记符表示如MOV传送、ADD相加、AND逻辑与每个助记符对应一个机器码。指令通常由操作码和操作数组成操作码指出做什么操作操作数指出对什么数操作、结果放何处。立即数指令中直接用#前缀表示的数据如MOV R1, #0x1245把 0x1245 送入 R1十六进制加0x前缀十进制直接写。1.3 Cortex-M3 支持的指令集指令集位宽特点适用场景ARM32 位性能高、代码密度低性能优先、32 位存储系统Thumb16 位代码密度高、性能较低成本/功耗优先、16 位存储系统Thumb-216/32 混合既高性能又高代码密度同时追求两者无需状态切换关键结论Cortex-M3只支持 Thumb-2 指令集不兼容传统 ARM 指令集不向后兼容。Thumb-2 是 Thumb 的超集含 16 位与 32 位指令编程时无需在 Thumb 与 ARM 状态间切换。相较传统 ARM 的优点① 不切换状态、省时省空间② 不必分别写 ARM/Thumb 源文件、开发与维护更简单③ 易得最优效率与性能。二、指令分类、条件域和指令格式2.1 Cortex-M3 指令分类Cortex-M3 是**加载/存储型load-store**架构指令仅处理寄存器中的数据结果放回寄存器访存须经专门的加载/存储指令。分为五大类数据传送指令MOV、LDR、STR…数据处理指令ADD、AND、CMP…跳转指令B、BL、BX…程序状态寄存器处理指令MRS、MSR异常处理指令带后缀S的指令会影响标志位带阴影的课本表 4-1为不常用指令。2.2 条件域条件执行Cortex-M3 几乎所有指令均可根据xPSR中的条件码有条件执行条件满足才执行否则忽略。每条指令含 4 位条件码位于指令最高 4 位 [31:28]共 16 种两个字符添加在助记符后。条件码判断依赖 APSR 四个标志位标志含义NNegative结果为负数时置 1ZZero结果为 0 时置 1CCarry无符号运算加法进位 / 减法借位减法则 C0 表示借位VoVerflow有符号运算溢出时置 116 种条件码助记符含义标志条件EQ相等Z1NE不相等Z0CS/HS进位置位 / 无符号≥C1CC/LO进位清 / 无符号C0MI负数N1PL正数或零N0VS溢出V1VC未溢出V0HI无符号高于C1 且 Z0LS无符号≤C0 或 Z1GE有符号≥NVLT有符号N≠VGT有符号Z0 且 NVLE有符号≤Z1 或 N≠VAL无条件默认不写条件码即为 AL应用示例CMP R0, R1 ; R0 - R1影响 APSR 标志 BGT Label ; 若 R0 R1有符号跳转到 LabelCMP R0, #10 ADDGT R1, R2, #5 ; 仅当 R0 10 才执行 R1 R2 5核心优势减少分支指令数量提升代码密度避免分支预测失败导致流水线清空提升执行效率。2.3 指令格式与伪指令助记符格式{Label} opcode {S} {cond} operand1, operand2 {, operand3} {;注释}标号Label指令所在地址的名字顶格写后接指令须有前导空格便于跳转与调试长度 ≤31 字符不与助记符重名。操作码opcode即助记符前面至少一个空格。后缀 S执行后根据结果更新 APSR 标志后缀 cond条件执行忽略时为 AL。操作数operand1 一般为目的寄存器operand2 可为寄存器operand3 可为寄存器或立即数。注释以分号;开头不影响执行。S 后缀示例ADD R3, R4 ; 不修改 APSR 的 C 标志 ADDS R3, R4 ; 修改 APSR 的 C 标志机器中指令的 5 个域32 位[31:28] 条件域 / [27:21] 操作码特征可选后缀 / [20] 是否影响标志 / [19:16] 基址寄存器 / [15:12] 目的或源寄存器 / [11:0] 偏移或操作数。统一汇编语言UAL为支持 Thumb-2汇编器引入 UAL——16 位与 32 位指令可统一用 32 位语法书写由汇编器决定用哪种可用.N窄16 位或.W宽32 位手工指定。注意传统 Thumb 语法默认更新 APSRUAL 下须显式加 S。AND R0, R1 ; 传统 Thumb 语法 ANDS R0, R0, R1 ; 等效 UAL必须有 S ADDS.N R0, #1 ; 指定 16 位 ADDS.W R0, #1 ; 指定 32 位常用伪指令不产生机器码伪指令作用AREA定义段CODE/DATA/READONLY/READWRITE…ENTRY指定程序入口一个源文件最多一个END源文件结束EQU定义数值常量如Test EQU 10DCB/DCW/DCD/DCFS/DCFD/SPACE数据定义字节/半字/字/单精/双精/留空LDR伪/ADR大范围/小范围地址读取注意LDR Rd,const与LDR Rd,label区别EXPORT声明全局标号可被其他文件引用WEAK 表示同名优先IMPORT引用其他文件的全局标号WEAK 表示找不到也不报错基本汇编源程序框架STACK_TOP EQU 0x20002000 ; 定义符号常量 STACK_TOP 0x20002000即 SRAM 栈顶地址SRAM 8KB起始 0x20000000 AREA RESET, CODE, READONLY ; 定义名为 RESET 的段属性为代码段(CODE)、只读(READONLY)链接到 Flash 起始处 DCD STACK_TOP ; 栈顶向量表第 0 项存放初始主堆栈指针 MSP 的值复位时硬件自动装入 MSP DCD START ; 复位向量向量表第 1 项存放复位处理程序地址复位时硬件自动装入 PC ENTRY ; 声明程序入口点告诉链接器从哪条指令开始执行 START ; 复位处理程序(Reset_Handler)的入口标号也是第 1 项向量指向的地址 LDR R0, 0x20002000 ; LDR 伪指令把地址 0x20002000 装入 R0作为待写入的内存地址 MOV R1, #0x5A ; 把立即数 0x5A 装入 R1作为待写入的数据 STR R1, [R0] ; 把 R1 的值存入 R0 指向的单元即 mem[0x20002000] 0x5A DEADLOOP ; 死循环入口标号 B DEADLOOP ; 无条件跳转到 DEADLOOP形成无限循环相当于 while(1) END ; 伪指令标志汇编源程序到此结束逐条详解 ① STACK_TOP EQU 0x20002000 EQU 是伪指令相当于 C 语言的 #define把符号 STACK_TOP 绑定为常量 0x20002000。Cortex-M 的 SRAM 通常映射在 0x20000000 起这里栈顶设为 0x20000000 0x2000说明片上 SRAM 为 8 KB0x2000 8192 字节栈从 SRAM 最高地址向低地址增长。 ② AREA RESET, CODE, READONLY AREA 伪指令用于划分段section。这里新建一个叫 RESET 的段属性是 CODE代码/可执行 READONLY只读、链接进 Flash。启动代码和向量表就放在这个段里链接后位于 Flash 起始 0x08000000复位时通过地址重映射在 0x00000000 被 CPU 取到。 ③ DCD STACK_TOP DCDDefine Constant Double-word在存储器中分配并初始化一个 32 位字。这是向量表第 0 项——Cortex-M 上电/复位后硬件自动从地址 0x00000000 取出第一个字装入主堆栈指针 MSP。所以这里必须放栈顶地址CPU 才知道堆栈从哪开始。 ④ DCD START 向量表第 1 项——复位异常向量。复位完成后硬件自动把这一项的内容即标号 START 的地址装入程序计数器 PC于是 CPU 跳到 START 处开始执行用户代码。 ⑤ ENTRY 伪指令告诉链接器程序的入口在这里。一个映像可以有多个 AREA但只能有一个 ENTRY链接器据此确定复位后真正该执行的第一条指令位置配合向量表第 1 项使用。 ⑥ START 标号标记后续指令的地址也就是复位处理程序Reset_Handler的入口与第④项的 DCD START 相呼应。 ⑦ LDR R0, 0x20002000 注意这里的 号——这是 LDR 伪指令不是 LDR Rd,[Rn] 的那条访存指令。作用是以任意 32 位立即数方式把 0x20002000 送进 R0。由于该数值较大、无法直接编码进 MOV 的 12 位立即数域汇编器会自动改用文字池literal poolPC 相对加载来实现。执行后 R0 0x20002000作为下一步写入操作的目标地址。 ⑧ MOV R1, #0x5A 把 8 位小常数 0x5A 送进 R1。0x5A二进制 0101_1010能直接编码进 MOV 的立即数域所以这是真正的 MOV 指令非伪指令。执行后 R1 0x5A即准备写入内存的数据。 ⑨ STR R1, [R0] STRStore Register把寄存器 R1 的值存入以 R0 内容为地址的存储单元即把 0x5A 写到内存地址 0x20002000。这是寄存器→内存的写操作和前面的 LDR内存→寄存器正好成对。 ⑩–⑪ DEADLOOP / B DEADLOOP B 是无条件分支指令B DEADLOOP 跳回自身标号构成无限空循环。相当于 C 语言的 while(1){}。在写完数据后让程序停在这里防止 PC 顺着往下跑飞到未知区域。 ⑫ END 伪指令告诉汇编器源文件到此结束其后内容不再参与汇编。 整体在做什么硬件视角 这是一段最小化启动代码它只做了三件事—— 在向量表首部放好 MSP 初值栈顶和 复位向量指向 START 复位后跳到 START把数据 0x5A 写入内存地址 0x20002000 进入死循环。三、寻址方式寻址方式根据指令中的地址信息寻找操作数物理地址的方式。Cortex-M3 主要寻址方式方式说明示例立即寻址操作数就在指令中立即数MOV R0, #0xFF000寄存器寻址操作数在寄存器中MOV R1, R2寄存器间接寻址寄存器的值为操作数地址LDR R1, [R2]寄存器移位寻址寄存器寻址后再移位MOV R0, R2, LSL #3R0R2×8基址变址寻址基址寄存器 偏移量[Rn,#off]、[Rn,#off]!预索引、[Rn],#off后索引、[Rn,Rm,LSL #n]多寄存器寻址一条指令传送多个寄存器LDMIA R0, {R1,R2,R3,R4}IA每读一字 R0 自增相对寻址以 PC 当前值为基址 偏移B Label偏移由汇编器计算经典考题MOV R1, #45采用的寻址方式是寄存器寻址 立即寻址R1 为寄存器45 为立即数。注意立即数不能作为目的操作数、存储器之间不能直接传送数据。四、Cortex-M3 指令集4.1 数据传送类指令指令功能MOV寄存器间或立即数→寄存器MOV R1,#0x5A、MOV R0,R1、MOV R3,R1,LSL#3MVN取反后传送MVN R1,#8→ R1 -9因为按位取反再求补码MOVW/MOVT16 位立即数→低 16 位高 16 清零/ 高 16 位低 16 不变LDR/LDRB/LDRH/LDRD存储器→寄存器字/字节/半字/双字B/H 加载时高位清零STR/STRB/STRH/STRD寄存器→存储器字/字节/半字/双字LDM/STM批量加载/存储如LDMIA R0!,{R2-R9}MRS/MSR特殊功能寄存器 ↔ 通用寄存器PUSH/POP堆栈入栈/出栈满递减堆栈PUSH {R0,R4-R7,LR}/POP {R0,R4-R7,PC}满递减堆栈SP 指向最后一个入栈数据向地址减小方向增长Cortex-M3 是满递减对应 LDMFD/STMFD。LDR vs STRLDR 内存→寄存器LoadSTR 寄存器→内存Store。4.2 数据处理类指令A算术运算指令功能示例ADD不带进位加法ADD R0,R1,R2R0R1R2ADC带进位加法C 参与用于 32 位加法96 位加法ADDS R0,R3,R6→ADCS R1,R4,R7→ADCS R2,R5,R8SUB不带进位减法SUB R0,R1,R2SBC带进位减法减去 !C96 位减法配 SUBS/SBCSRSB/RSC逆向减法R2-R1/ 带进位逆向减法RSB R0,R1,#112112-R1MUL/MLA32 位乘法 / 乘加MLA R0,R1,R2,R3R0R1×R2R3SMULL/SMLAL64 位有符号乘 / 乘加结果低 32 位在 Low、高 32 位在 HighUMULL/UMLAL64 位无符号乘 / 乘加同上MLS32 位乘减R0R1×R2-R3UDIV.W/SDIV.W无符号/有符号除法RdRn/Rm丢弃余数除零触发用法 Fault若 NVIC 的 DIVBYZERO 置位B逻辑运算指令功能AND逻辑与AND R0,R0,#0x03→ 取低 2 位ORR逻辑或ORR R0,R0,#0x03→ 置位低 2 位ORN逻辑或非立即数取反后或EOR逻辑异或EOR R0,R0,#0x03→ 反转低 2 位BIC位清除BIC R0,R0,#0x0b→ 清位 0/1/3NEG求补Rd 0 - Rm ~Rm 1C比较指令只更新标志不存结果指令功能CMP比较Rn - op2设标志CMN反值比较Rn op2设标志TST按位与测试检测特定位TEQ按位异或测试判断是否相等D移位指令桶型移位器支持 6 种移位说明LSL/ASL逻辑/算术左移低位补 0等价可互换LSR逻辑右移左端补 0ASR算术右移左端补第 31 位保留符号ROR循环右移左端用右端移出位补RRX带扩展循环右移右移 1 位高端用原 C 标志补其他数据处理数据翻转、数据扩展、位段处理、饱和运算指令课本 E 类。4.3 跳转指令指令全称功能保存返回地址BBranch基本跳转相对前后约 32 MB否BLBranch with Link跳转前把 PC 存入 LRR14是子程序调用BXBranch and eXchange跳到寄存器地址更新 T 位BX LR用于函数返回可选BLXBranch with Link and eXchangeBL BX 结合是CBZ/CBNZCompare and Branch if Zero/Non-zero比较为零/非0即跳转仅前向范围 4~130不更新标志否TBB/TBHTable Branch Byte/Halfword查表转移字节/半字为单位的前向跳转—ITIf-Then围起 1~4 条可条件执行指令块—NOPNo Operation无操作常用于延时—B 指令 32 MB 范围由来26 位偏移可表示 2²⁶ 67,108,864 字节 64 MB故前后各 32 MB。CBZ CMP Rn,#0 BEQ合二为一减少代码尺寸、提高效率。IT 块规则最多 4 条含 T条件成立执行/ E否则执行T 对应指令用相同条件E 对应用相反条件IT 不可嵌套块内不可含 CBZ/CBNZ/CPSID/CPSIE改 PC 的指令须在块内最后或块外除带条件 B 外的所有条件指令须在块内。有如下例题if (R0R1) { R3R4R5; R3R3*2; } else { R3R6R7; R3R3/2; }其对应的汇编语言程序案例CMP R0, R1 ; 比较 R0 与 R1算 R0−R1 并置标志位结果不保存相等则 Z 标志置 1 ITTEE EQ ; IT 块Thumb-2 条件执行框架后续 4 条按 EQ 分两组 —— 前两条「then」相等时执行后两条「else」不等时执行 ADDEQ R3, R4, R5 ; 若 R0R1EQR3 R4 R5 LSLEQ R3, R3, #1 ; 若 EQR3 逻辑左移 1 位即乘 2 ADDNE R3, R6, R7 ; 若 R0!R1NE即 else 分支R3 R6 R7 ASRNE R3, R3, #1 ; 若 NER3 算术右移 1 位即除 2保留符号位4.4 其他指令SWI软件中断、BKPT断点、SEV发送事件、WFE休眠待事件唤醒、WFI休眠待中断唤醒、ISB指令同步隔离、DSB数据同步隔离、DMB数据存储隔离。五、汇编程序设计5.1 分支程序多执行路径条件指令实现CMP R5,#10→MOVNE R0,R5/MOVEQ R1,R5条件跳转实现CMP R5,#10→BEQ R5EQ10→MOV R0,R5→B CMPENDR5EQ10: MOV R1,R5多分支跳转表把各分支首地址依次放入跳转地址表分支点用LDR PC,[R5,R0,LSL #2]取地址送 PC。MOV R0, N ; 将跳转索引值 N 装入寄存器 R0N 即 switch 的选择值决定跳到第几个分支 ADR R5, JPTAB ; 将跳转表首地址 JPTAB 读入 R5ADR 是伪指令按 PC 相对偏移算出表的运行时地址 LDR PC, [R5, R0, LSL #2] ; 以 R5R0×4 为地址取出一个字装入 PC实现按索引的间接跳转每表项 4 字节R0 左移 2 位即乘 4 JPTAB ; 跳转表散转表标号其下依次存放各分支的入口地址 DCD FUNC0 ; 跳转表第 0 项存入 FUNC0 入口地址R00 时经上面那条指令跳转到 FUNC0 DCD FUNC1 ; 跳转表第 1 项存入 FUNC1 入口地址R01 时跳转到 FUNC1 DCD FUNC2 ; 跳转表第 2 项存入 FUNC2 入口地址R02 时跳转到5.2 循环程序重复执行循环体满足条件重复即为循环被重复段为循环体while 先判后执行do-while 先执行后判。示例复制 80 个字用LDMIA/STMIA每次搬 8 字循环 10 次。LDR R1, DATA_SRC ; 将源数据标号 DATA_SRC 的地址装入 R1R1 作为源指针 是伪指令从常量池取该地址 LDR R0, DATA_DST ; 将目的标号 DATA_DST 的地址装入 R0R0 作为目的指针 MOV R10, #10 ; 把循环计数 R10 设为 10共搬 10 批每批 8 个字 LOOP ; 循环标号下面每轮迭代负责拷贝一批8 个字 LDMIA R1!, {R2-R9} ; 从 [R1] 连续取 8 个字装入 R2–R9然后 R1 自增 32! 回写IA存/取后地址递增8×432 字节 STMIA R0!, {R2-R9} ; 把 R2–R9 连续写回到 [R0]然后 R0 自增 32完成这 8 个字的搬移 SUBS R10, R10, #1 ; R10 减 1 并更新条件标志S 后缀据此判断循环是否结束 BNE LOOP ; 若 R10 不为零Z 标志0则跳回 LOOP 继续下一批减到 0 退出循环5.3 子程序的调用与返回子程序可多次调用首条指令前须有标号子程序名主程序用BL调用。子程序末尾用MOV PC,LR或BX LR将返回地址送回 PC。STACK_TOP EQU 0x20002000 ; 定义符号 STACK_TOP值 0x20002000片上 SRAM 顶端作为复位后主堆栈指针 MSP 的初始地址 AREA RESET, CODE, READONLY ; 声明一个名为 RESET 的存储区CODE 表示代码段、READONLY 表示只读链接进 Flash DCD STACK_TOP ; 向量表第 1 字Cortex-M 复位时硬件自动把该值装入 MSP即初始栈顶 DCD START ; 向量表第 2 字复位向量芯片复位后跳转到 START 开始执行 ENTRY ; 告诉链接器程序的入口点第一条被执行的指令所在用于设置复位向量目标 START ; 复位处理入口标号与上面复位向量 DCD START 对应程序真正启动处 MOV R1, #0x59 ; 将立即数 0x59 装入通用寄存器 R1作为后续加法运算的操作数之一 MOV R0, #0x28 ; 将立即数 0x28(十进制 40) 装入通用寄存器 R0另一个操作数 BL FUNC1 ; 带返回地址调用 FUNC1先把下一条指令地址存入 LR再跳转到 FUNC1 B . ; 跳转到当前地址自身. 表示本行地址形成无限循环防止主程序跑飞 FUNC1 ; 子程序 FUNC1 的标号由上面的 BL 调用进入 ADDS R2, R1, R0 ; 带状态标志的加法R2 R1 R00x59 0x28S 后缀使结果更新 APSR 条件标志 MOV PC, LR ; 将 LR返回地址赋给 PC从而返回到调用者即 BL 之后的 B . 处 END ; 源文件结束指示告知汇编器后续不再翻译本章小结与思考题核心知识地图汇编语言简介机器/汇编/高级三层、助记符、Thumb-2 仅支持指令分类五大类、条件域N/Z/C/V 16 种条件码、指令格式与 UAL、伪指令七种寻址方式立即/寄存器/间接/移位/基址变址/多寄存器/相对Cortex-M3 指令集数据传送 MOV/MVN/LDR/STR/批量/堆栈数据处理 算术/逻辑/比较/移位跳转 B/BL/BX/CBZ/IT其他隔离指令汇编程序设计分支/循环/子程序调用与返回
返回列表