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

ARM汇编代码新手入门

为什么要学 ARM 汇编?

汇编是直接操作硬件的 “机器语言翻译”,在嵌入式开发中(如芯片驱动、实时系统)不可替代; 例:STM32 芯片的启动代码必须用汇编编写,因为 C 语言无法直接初始化 CPU 寄存器。

ARM 架构与寄存器(重点)

ARM 是什么

一种主流嵌入式处理器架构(手机、汽车芯片、物联网设备常用),我们以 32 位 ARMv7 架构为例(Cortex-M/R 系列通用)。

寄存器:CPU 内部的 “临时存储器”(比内存快 1000 倍),ARM 有 16 个通用寄存器(r0-r15),重点记住这几个特殊寄存器:

r0-r3:传递函数参数 / 返回值(类似快递盒);

sp(r13):栈指针(指向当前栈顶,类似 “临时工作台”);

lr(r14):链接寄存器(存函数返回地址,类似 “回家的路牌”);

pc(r15):程序计数器(存下一条要执行的指令地址,类似 “当前页码”)。

类比:寄存器就像厨房的 “调料罐”,常用的调料(数据)放在罐子里,炒菜(运算)时直接拿,比从仓库(内存)取快得多。

汇编程序基本结构

    .text        ; 代码段(存放指令).global main ; 声明程序入口
main:            ; 程序入口(类似C的main)mov r0, #5   ; r0 = 5(#表示常数)mov r1, #3   ; r1 = 3add r2, r0, r1 ; r2 = r0 + r1(结果8)bx lr        ; 程序结束(返回)

练习

  1. 写出mov r3, #10的作用。
  2. 补全程序:用sub指令实现r4 = r0 - r1(已知r0=8,r1=3)。

解析

1.mov r3, #10:将常数 10 存入寄存器r3r3 = 10)。

2.

mov r0, #8    ; r0 = 8
mov r1, #3    ; r1 = 3
sub r4, r0, r1 ; r4 = 8 - 3 = 5

基础指令与运算

1. 数据传送指令

  • mov rd, rnrd = rn(寄存器间传值);
  • mov rd, #immrd = 常数(传常数);
  • ldr rd, [rn]:从rn指向的内存读数据到rd(内存→寄存器);
  • str rd, [rn]:把rd的值写到rn指向的内存(寄存器→内存)。

2. 算术运算指令

  • add rd, rn, rmrd = rn + rm
  • sub rd, rn, rmrd = rn - rm
  • mul rd, rn, rmrd = rn × rm

练习

  1. 编写程序:计算10 - (2 + 3),结果存r5
  2. ldr/str指令实现:将内存地址0x20000000中的值加 10 后,写回原地址。

解析

1.

mov r0, #2    ; r0 = 2
mov r1, #3    ; r1 = 3
add r2, r0, r1 ; r2 = 2 + 3 = 5(先算括号内)
mov r3, #10   ; r3 = 10
sub r5, r3, r2 ; r5 = 10 - 5 = 5(最终结果)

2.

ldr r0, =0x20000000 ; r0 = 内存地址(=表示取地址)
ldr r1, [r0]        ; r1 = 从0x20000000读的值(假设原 value=5)
add r1, r1, #10     ; r1 = 5 + 10 = 15
str r1, [r0]        ; 把15写回0x20000000
  • ldr r0, =0x20000000:将内存地址存入r0(注意=的用法);
  • ldr/str配合[rn]实现内存访问。

程序流程控制(分支与循环)

1. 无条件跳转

b label:跳转到label标签(类似goto)。

2. 条件跳转(重点)

ARM 通过CPSR 寄存器(程序状态寄存器)的 “条件码” 判断跳转,常用条件:

eq(等于)、ne(不等于)、gt(大于)、lt(小于)。

指令格式:b<条件> label(如beq label:等于则跳转)。

例:if-else 逻辑

  cmp r0, r1   ; 比较r0和r1(结果存CPSR)beq equal    ; 若相等,跳equalmov r2, #0   ; 不相等:r2=0b end        ; 跳end
equal:mov r2, #1   ; 相等:r2=1
end:

3. 循环结构

用 “条件跳转 + 自增” 实现循环。

练习

  1. 编写程序:判断r0是否为偶数(提示:偶数的二进制末位为 0,用and指令)。
  2. 计算 1~5 的乘积(1×2×3×4×5),结果存r2

解析

1.判断偶数代码:

mov r0, #6    ; 假设r0=6(偶数)
and r1, r0, #1 ; r1 = r0 & 1(取末位,偶数末位0,奇数末位1)
cmp r1, #0    ; 比较r1是否为0
beq even      ; 若等于0,跳even
mov r2, #0    ; 奇数:r2=0
b endeven:
mov r2, #1 ; 偶数:r2=1
end:

2.

2. 计算乘积代码:  
```asm
mov r0, #1    ; r0=1(乘积初始值)
mov r1, #1    ; r1=1(当前数,从1开始)
loop:
mul r0, r0, r1 ; 乘积 = 乘积 × 当前数(1×1→1×2→2×3→...)
add r1, r1, #1 ; 当前数+1(1→2→3→4→5→6)
cmp r1, #6    ; 判断当前数是否>5(因为要乘到5)
blt loop      ; 若<6,继续循环
mov r2, r0    ; 结果存r2(r2=120)

函数调用与栈操作

1. 函数调用流程

  • 调用:bl 函数名(跳转 + 保存返回地址到lr);
  • 返回:bx lr(跳回lr存的地址)。

2. 栈的作用:保存现场

函数内部可能覆盖寄存器,需用栈保存状态:

  • push {r0-r3, lr}:压栈保存寄存器;
  • pop {r0-r3, pc}:出栈恢复(pc=lr实现返回)。

练习

  1. 编写函数sub_func,接收r0(a)和r1(b),返回a - b,在main中调用。
  2. 编写函数max,接收r0r1,返回较大的数。

解析

.global main
main:
mov r0, #10 ; a=10
mov r1, #3 ; b=3
bl sub_func ; 调用函数,返回值存 r0(10-3=7)
bx lrsub_func: ; 函数:返回 r0 - r1
sub r0, r0, r1 ; 计算差
bx lr ; 返回

2. 求最大值函数代码:  


.global main
main:
mov r0, #5    ; 参数1=5
mov r1, #8    ; 参数2=8
bl max        ; 调用max,返回值存r0(8)
bx lrmax:            ; 函数:返回r0和r1中的最大值
cmp r0, r1   ; 比较
bge greater  ; 若r0 >= r1,跳greater
mov r0, r1   ; 否则r0 = r1(让r0存较大值)
b end
greater:
; 若r0更大,无需操作
end:
bx lr        ; 返回r0

http://www.dtcms.com/a/336738.html

相关文章:

  • 信号量机制中---生产者 - 消费者问题
  • LeetCode 1323: 6和9组成的最大数字
  • 计算机网络技术学习-day2《IP地址分类解析》
  • 中国星网发展情况全面分析
  • 每日Java面试系列(15):进阶篇(String不可变的原因、性能问题、String三剑客、自定义不可变设计、组合优于继承等相关问题)
  • 数据结构——线性表
  • 蓝桥杯C++
  • 下降路径最小和
  • 《Java高并发核心编程》笔记汇总
  • 【Java企业级开发】(八)Spring框架中Web项目构建
  • 【高等数学】第九章 多元函数微分法及其应用——第六节 多元函数微分学的几何应用
  • Transformer架构的数学本质:从注意力机制到大模型时代的技术内核
  • AI 编程在老项目中的困境与改进方向
  • 负载测试与压力测试详解
  • MySQL黑盒子研究工具 strace
  • 基于因果性的深层语义知识图谱对文本预处理的积极影响
  • Perf使用详解
  • AI系统性思维复盘概述
  • 【FreeRTOS】事件组
  • 电力设备状态监测与健康管理:从数据感知到智能决策的技术实践​
  • 通达信【牛股妖股埋伏】副图+选股指标
  • 报错注入原理与全方法总结
  • HAL-ADC配置
  • 快速了解均值滤波处理
  • 关于动态代理的个人记录
  • CF2121B Above the Clouds
  • 【Java】多线程Thread类
  • 什么是AIGC(人工智能生成内容)
  • 牛客周赛 Round 104(小红的树不动点)
  • 人工智能入门②:AI基础知识(下)