当前位置: 首页 > news >正文

汇编语言的基础使用

本篇简单介绍了关于汇编的一些基础指令的用法,但关于栈、寄存器等问题还未写入,会在后面的时间进行补充,汇编会用的语言基础环境依然是keil 4,但需要有相关支持,其他更多的指令建议大家多查手册来学习

学习核心目标

编写ARM 启动代码,为 C 语言运行搭建基础环境,核心任务包括:

  1. 初始化异常向量表(处理复位、中断等异常)
  2. 初始化各工作模式的栈指针寄存器(C 语言函数调用依赖栈)
  3. 开启 ARM 内核中断允许(配置 CPSR 寄存器)
  4. 将工作模式切换为User 模式(用户程序运行模式)
  5. 引导程序进入 C 语言main函数执行

一、ARM 汇编基础(格式与伪指令)

1. 汇编程序基本结构(汇编中注释用;)

ARM 汇编通过伪指令指导汇编器工作,非处理器指令,核心结构如下:(注意格式:最前面要加tab键)

    AREA reset, CODE, READONLY  ; 定义代码段,段名reset(复位向量段),属性只读CODE32                      ; 后续指令使用32位ARM指令集(Thumb为16位,需用THUMB伪操作)ENTRY                       ; 标记程序入口(复位后第一个执行的指令位置); 具体内容END                         ; 标记程序结束

2. 关键伪指令解析

伪操作作用说明
AREA定义段(代码段 / 数据段 / 栈段),格式:AREA 段名, 段属性, 访问权限
CODE32/THUMB指定指令集类型:32 位 ARM 指令集 / 16 位 Thumb 指令集
ENTRY标记程序入口,一个工程仅一个 ENTRY(复位向量段需包含 ENTRY)
END标记汇编文件结束,汇编器遇到 END 后停止处理

二、核心 ARM 指令

1. 数据传送指令(MOV/MVN)

(1)MOV 指令(数据移动 / 赋值)
  • 功能:将立即数或寄存器值传送到目标寄存器(类似 C 语言的 = 赋值)

  • 指令格式

    格式说明示例
    MOV{S}<c> Rd, #const立即数传送到 RdMOV R0, #0x8(R0=8)
    MOV{S}<c> Rd, RmRm 值传送到 RdMOV R1, R0(R1=R0)
    MOV{S}<c> Rd, Rm, <shift>Rm 移位后传送到 Rd(移位量 0-31)MOV R6, R0, LSL #31(左移 31 位)

关键注意点

  • 移位操作支持LSL(逻辑左移)、LSR(逻辑右移)、ASR(算术右移)、ROR(循环右移)、RRX(带进位循环右移,无需移位量)
  • 立即数需满足12 位立即数规则<z在SUB指令部分所写>
(2)MVN 指令(按位取反)
  • 功能:将立即数或寄存器值按位取反后传送到目标寄存器(类似 C 语言 ~)
  • 指令格式MVN{S}<c> Rd, #const / MVN{S}<c> Rd, Rm{, <shift>}
  • egMVN R0, #0x0(R0=0xFFFFFFFF,因为 0x0 取反为全 1)

2. 算术运算指令(ADD/SUB/CMP)

(1)ADD 指令(加法)
  • 功能:两个操作数相加,结果存入目标寄存器(类似 C 语言+

  • 指令格式

    格式说明示例
    ADD{S}<c> Rd, Rn, #constRn + 立即数 → RdADD R6, R0, #0xF0
    ADD{S}<c> Rd, Rn, Rm{, <shift>}Rn + (Rm 移位后) → RdADD R7, R0, R1, LSL #1(R0+2*R1)
  • 注意:无ADD Rd, #a, #b格式(C 语言a+b在编译阶段计算,无需机器指令)

(2)SUB 指令(减法)
  • 功能:两个操作数相减,结果存入目标寄存器(类似 C 语言-

  • 指令格式(与 ADD 类似):

    • SUB{S}<c> Rd, Rn, #const(Rn - 立即数 → Rd)
    • SUB{S}<c> Rd, Rn, Rm{, <shift>}(Rn - 移位后的 Rm → Rd)
  • 关键补充:

    什么是立即数?

    立即数是直接嵌入在指令中的常数,无需从内存、寄存器中读取,CPU 可直接用该常数参与运算,它的核心特点是 “指令自带数据”,能减少内存访问次数,提升指令执行效率。

    12 位立即数规则

    • 判断标准:一个数展开为 32 位二进制后,存在偶数位循环右移,使移位后高 24 位全 0,低 8 位为有效imm8(循环移位次数2N,N=0~15 -> 2N = 0~30)
    • 原因:ARM 指令为 32 位,立即数由4位循环移位量(N)+8位imm8组成,共 12 位(即imm12
    • eg#0x80000000(二进制1000...0000)可通过imm8=0x80、循环移位2*15=30位得到,属于合法立即数;#0x101无法通过该规则得到,为非法立即数
(3)CMP 指令(比较)
  • 功能:比较两个数(本质是SUB运算,但不保存结果,仅更新 CPSR 标志位)[通过做差得到的正负值来判断二者大小]
  • 指令格式CMP<c> Rn, #const / CMP<c> Rn, Rm{, <shift>}
  • 等价关系CMP R0, R1 ≡ SUBS R0, R1S表示更新标志位)
  • 用途:配合条件跳转指令(如BLEBGT)实现分支逻辑

用subs实现指令比较(cmp作用)流程图

条件判断标志NZCV
CPSR寄存器中条件判断标志位
N: 符号标志位:上条指令执行结果最高位bit31为1,则 N = 1, 当结果作为有符号解释时为负值;
Z: 零值标志位:上条指令执行结果为0(即bit0 - bit31 均为0),则 Z = 1;
C: 进位标志位:进行无符号解读,如果在加法过程中进位或者减法时没有借位,则为 C = 1,否则 C = 0
V: 溢出标志位:进行有符号解读,是否发生溢出 -2^31 - 2^31-1(两个正数加得负数,两个负数加得正数)
条件码:eq ge gt le lt al(无条件执行)
equal:等于
not equal:不等于

3. 位操作指令(BIC/ORR)

(1)BIC 指令(指定位清0)
  • 功能:将 Rn 的指定位清 0(按 Rm / 立即数的位掩码),结果存入 Rd(类似 C 语言Rn & ~mask
  • 指令格式BIC{S}<c> Rd, Rn, #const / BIC{S}<c> Rd, Rn, Rm{, <shift>}
  • eg
    MOV R0, #0xFFFFFFFF  ; R0=全1
    MOV R1, #1
    BIC R2, R0, R1, LSL #31  ; R0的bit31清0 → R2=0x7FFFFFFF
    
(2)ORR 指令(指定位置1)
  • 功能:将 Rn 的指定位置 1(按 Rm / 立即数的位掩码),结果存入 Rd(类似 C 语言Rn | mask
  • 指令格式ORR{S}<c> Rd, Rn, #const / ORR{S}<c> Rd, Rn, Rm{, <shift>}
  • eg
    MOV R0, #0x00        ; R0=全0
    MOV R1, #1
    ORR R8, R0, R1, LSL #31  ; R0的bit31置1 → R8=0x80000000
    

4. 内存访问指令(LDR)

LDR 指令(加载)
  • 功能:从内存地址读取数据到寄存器
  • 核心格式
    • 加载立即数地址:LDR Rd, =const(伪指令,将 32 位地址存入 Rd,解决MOV Rd, #const无法处理大地址的问题)
    • 加载标签地址:LDR Rd, <label>(将标签对应的内存地址值存入 Rd)
  • egLDR SP, =0x40001000(初始化栈指针为0x40001000MOV SP, #0x40001000会报错,因地址超 12 位立即数范围)
STR (存放指令)​

功能:​​ 将寄存器中的数据写入​(存储)到指定的内存地址中。

核心格式:​STR<c> <Rt>, <addressing_mode>

5. 跳转与函数调用指令(B/BL/BX)

指令功能说明示例用途场景
B无条件 / 条件跳转,不保存返回地址B loop(跳转到 loop 标签)循环、简单分支
BL跳转并保存返回地址到LR(Link Register)BL func(调用 func 函数)函数调用(需返回主调函数)
BX跳转并切换指令集(ARM/Thumb)BX LR(从 LR 恢复 PC,返回)函数返回(等价于MOV PC, LR
  • 等价关系B fun ≡ LDR PC, =fun(PC 为程序计数器,指向当前执行指令地址 + 8)

三、重要应用

1. 循环实现(对应 C 语言循环结构)

循环三要素
循环结束条件
推动循环趋向终结的语句
循环的循环体

(1)do-while 循环(先执行循环体,再判断条件)

C 语言原码:

int i = 0;
int sum = 0;
do {sum += i;i++;
} while (i <= 100);

汇编实现:

    MOV R0, #0            ; R0 = i = 0MOV R1, #0            ; R1 = sum = 0
loopADD R1, R1, R0        ; sum += iADD R0, R0, #1        ; i++CMP R0, #100          ; 比较i和100BLE loop              ; 若i<=100,跳回loop(BLE=Branch if Less than or Equal)
(2)while/for 循环(先判断条件,再执行循环体)

C 语言原码

int i = 0;
int sum = 0;
while (i <= 100) {sum += i;i++;
}

汇编实现:

    MOV R0, #0               ; R0 = i = 0MOV R1, #0               ; R1 = sum = 0
loopCMP R0, #100             ; 先判断i<=100?BGT finish               ; 若i>100,跳至finish(BGT=Branch if Greater Than)ADD R1, R1, R0           ; sum += iADD R0, R0, #1           ; i++B loop                   ; 跳回loop继续判断
finishB finish                 ; 死循环(防止程序跑飞)

2. 函数定义与调用(含现场保护)

(1)函数调用核心问题
  • 问题 1:被调函数修改主调函数的寄存器,导致数据丢失
  • 问题 2:函数嵌套时,LR被覆盖,无法正确返回
  • 解决方案:栈保护现场(入栈保存寄存器,出栈恢复)
(2)汇编函数调用(嵌套调用)
PRESERVE8               ; 栈8字节对齐,解决C函数调用报错
AREA func_demo, CODE, READONLY
ENTRYmain:
LDR SP, =0x40001000     ; 初始化栈指针(关键:必须先初始化栈)
STMFD SP!, {R0-R12, LR} ; 保护main的现场(寄存器+返回地址)
BL func0                ; 调用func0,LR保存main的返回地址
LDMFD SP!, {R0-R12, LR} ; 恢复main的现场
MOV R3, #300            ;

文章转载自:

http://0stbVC5S.rpwht.cn
http://EIJezw6A.rpwht.cn
http://mQrB5sG3.rpwht.cn
http://pXtUioBD.rpwht.cn
http://4jIRFaGV.rpwht.cn
http://k9RdOQM7.rpwht.cn
http://SLKMVqfP.rpwht.cn
http://fEMdq6Rn.rpwht.cn
http://ymy4sBl4.rpwht.cn
http://qVrnG7vW.rpwht.cn
http://tke7GDLd.rpwht.cn
http://wtuzMAl1.rpwht.cn
http://8zHXYaNn.rpwht.cn
http://1VY4SOKs.rpwht.cn
http://Bip4TSFV.rpwht.cn
http://0gU0CWHt.rpwht.cn
http://5HwZcrKi.rpwht.cn
http://uZxgpc9p.rpwht.cn
http://hfEsBdPI.rpwht.cn
http://gOA4vDdc.rpwht.cn
http://BcoDGIJQ.rpwht.cn
http://wvXpTHLd.rpwht.cn
http://Go8fRFXX.rpwht.cn
http://Zduq1Al4.rpwht.cn
http://8FyNCMMq.rpwht.cn
http://AcfC8AOG.rpwht.cn
http://9UIwvXFM.rpwht.cn
http://ijfFsrb7.rpwht.cn
http://KtkB6zrm.rpwht.cn
http://gBidWuHR.rpwht.cn
http://www.dtcms.com/a/373515.html

相关文章:

  • networkx图节点重要性分析探索-k_core和betweenness_centrality
  • redis集群(去中心化)原理+配置集群+集群扩容、缩容完整实验流程
  • 信息摘要、数字签名与数字证书:构建网络信任体系的三重保障
  • N76E003新唐MCU实现将变量保存到flash实现非易失存储IAP
  • Java开发中常用CollectionUtils方式,以及Spring中CollectionUtils常用方法示例
  • PL/SQL远程连接Oracle数据库
  • Python学习之装饰器
  • 基于STM32单片机的盲人拐杖超声波测距GSM短信报警语音播报录音灯光控制
  • Aider AI Coding 项目 RepoMap 模块深度分析
  • Linux 初识
  • 直播预告 | 开源低代码框架 Erupt 全生态讲解
  • LAMPSecurity: CTF7靶场渗透
  • 基于cornerstone3D的dicom影像浏览器 第六章 在Displayer中显示图像方位
  • CTFHub靶场之SSRF POST请求
  • Java 大视界 -- 基于 Java 的大数据分布式存储在智慧城市时空大数据管理与应用中的创新实践(408)
  • 人工智能中的线性代数总结--简单篇
  • TightVNC功能介绍
  • 华为2288H V5服务器安装openEuler系统及可视化界面注意点
  • elementui tabs动态渲染+锚点滚动定位
  • 嵌入式 - ARM(2)汇编
  • php计算一个模拟增长过程函数
  • ElementUI 中 validateField 对部分表单字段数组进行校验时多次回调问题
  • DevOps实战(4) - 使用Arbess+GitLab+SourceFare实现Java项目自动化部署
  • Oracle数据库简单查询语句的方法
  • 【红日靶场】vulnstack1
  • 华为麒麟操作系统运维常见知识点
  • 微算法科技(NASDAQ: MLGO)采用分片技术(Sharding)与异步共识机制,实现节点负载均衡,提升交易处理效率
  • 【113】基于51单片机MP3音乐播放器【Keil程序+报告+原理图】
  • 后端开发技术栈
  • 疯狂星期四文案网第64天运营日记