1. 什么是自定义汇编语言(Custom Assembly Language)?
汇编语言(Assembly Language)是一种低级编程语言,它直接与 CPU 指令集(Instruction Set Architecture, ISA)对应,每条指令都映射到机器码(Binary Code)。自定义汇编语言通常指:
-
为特定 CPU 设计的汇编语言(如 x86、ARM、RISC-V)
-
基于虚拟机(VM)的汇编语言(如 WebAssembly、JVM 的字节码)
-
专用于特定系统的汇编指令集(如 GPU 汇编)
🛠️ 汇编语言的编程原则
-
寄存器操作:使用
MOV
、ADD
、SUB
等指令操作 CPU 寄存器。 -
内存管理:手动处理
STACK
(栈)和HEAP
(堆)。 -
条件跳转 & 循环:使用
CMP
+JMP
(如JE
、JNE
)来实现分支逻辑。 -
系统调用(Syscall):调用操作系统提供的功能(如文件 I/O)。
示例(x86 汇编 - NASM 语法):
section .data
message db "Hello, Assembly!", 0 ; 定义字符串
section .text
global _start
_start:
mov edx, 16 ; 设置要输出的字符数量
mov ecx, message ; 指向 message 地址
mov ebx, 1 ; 文件描述符 (stdout)
mov eax, 4 ; syscall: sys_write
int 0x80 ; 触发中断,执行系统调用
mov eax, 1 ; syscall: sys_exit
xor ebx, ebx ; 退出状态码 0
int 0x80
- 2. Unix 简介
Unix 是一个强大且稳定的操作系统,强调多用户、多任务、权限管理。许多现代操作系统(如 Linux、macOS、BSD)都基于 Unix 设计。
🔧 Unix 基础
-
命令行操作(Shell):
ls
、cd
、pwd
、grep
-
进程管理:
ps
、kill
、top
-
文件权限:
chmod
、chown
-
系统调用(Syscall):用户程序调用内核功能(如
open()
、read()
、write()
示例
ls -l # 查看当前目录详细信息
chmod +x script.sh # 赋予脚本执行权限
ps aux # 显示所有进程
- 3. Git 简介
Git 是一种分布式版本控制系统(DVCS),主要用于代码管理、团队协作、历史追踪。
Git 常用命令
git init # 初始化 Git 仓库 git clone <repo_url> # 克隆远程仓库 git add file.txt # 添加文件到暂存区 git commit -m "提交说明" # 提交更改 git push origin main # 推送到远程仓库 git pull origin main # 拉取最新代码 git log # 查看提交历史
2. 熟悉 Unix 基本命令
查看和切换目录
pwd # 显示当前目录(Print Working Directory)
ls # 列出当前目录下的文件和文件夹
ls -l # 详细信息(long format)
ls -a # 显示所有文件(包括隐藏文件)
ls -lh # 以可读格式显示文件大小(KB/MB)
cd /path # 进入指定目录
cd .. # 返回上一级目录
cd - # 返回上次访问的目录
创建、删除目录
mkdir myfolder # 创建目录
rmdir myfolder # 删除空目录
rm -r myfolder # 删除非空目录(慎用)
创建、复制、移动和删除文件
touch file.txt # 创建文件
cp file1.txt file2.txt # 复制文件
mv file.txt newname.txt # 重命名/移动文件
rm file.txt # 删除文件(不可恢复)
2.2 查看和编辑文件
cat file.txt # 显示文件内容
less file.txt # 分页查看文件(按 `q` 退出)
head -n 10 file.txt # 显示前 10 行
tail -n 10 file.txt # 显示后 10 行
nano file.txt # 使用 Nano 编辑器编辑文件
vim file.txt # 使用 Vim 编辑文件(高级)
2.3 用户管理
whoami # 显示当前用户
who # 查看当前在线用户
id # 显示当前用户的 UID 和 GID
passwd # 修改当前用户密码
sudo su # 切换到 root 用户(需要 sudo 权限)
2.4 权限管理
查看权限
ls -l file.txt
示例输出:
-rw-r--r-- 1 user user 1234 Mar 31 12:00 file.txt
-
-rw-r--r--
:文件权限 -
user user
:文件的所属用户和用户组
修改权限
chmod 644 file.txt # 允许所有人读取,只有文件所有者可以写
chmod +x script.sh # 赋予执行权限
chown newuser file.txt # 更改文件所有者
2.5 进程管理
ps aux # 显示所有进程
top # 动态显示进程信息(按 `q` 退出)
htop # 更美观的进程管理工具(需要安装)
kill PID # 终止进程(用 `ps aux` 找到 PID)
kill -9 PID # 强制终止进程
pkill name # 按进程名称终止
2.6 磁盘和存储管理
df -h # 显示磁盘空间使用情况
du -sh * # 查看当前目录下每个文件/文件夹的大小
mount # 查看挂载的磁盘
umount /dev/sdb1 # 卸载设备
2.7 搜索与查找
find /path -name "file.txt" # 按文件名查找
find / -size +100M # 查找大于 100MB 的文件
grep "error" file.txt # 在文件中查找 "error"
grep -r "keyword" /path/ # 递归搜索目录
2.8 网络管理
ping google.com # 检查网络连接
curl ifconfig.me # 查看公网 IP 地址
wget http://example.com/file.zip # 下载文件
netstat -tulnp # 查看当前网络连接
练习任务
你可以尝试以下任务来熟练 Unix 命令:
-
创建一个新目录
testdir
并进入它。 -
创建一个文本文件
notes.txt
并写入一些内容。 -
复制
notes.txt
到backup.txt
并查看其内容。 -
查找
/etc
目录中所有.conf
文件。 -
杀死一个运行中的进程(使用
ps aux
找到进程)。 -
查看你的磁盘使用情况 并找到大于 100MB 的文件。
3. 学习 Git 进行代码版本管理
Git 基础概念
🔹 Git 是什么?
Git 允许你追踪代码的每次修改,随时回溯历史,并与团队协作。
🔹 常见术语
术语 | 解释 |
---|---|
Repository(仓库) | 存储代码和历史记录的地方 |
Commit(提交) | 记录代码的某次修改 |
Branch(分支) | 独立的开发线,允许并行工作 |
Merge(合并) | 将分支的更改合并到主分支 |
Remote(远程仓库) | 存储在 GitHub、GitLab 等远程服务器的仓库 |
Git 安装与配置
安装 Git
Linux (Debian/Ubuntu)
sudo apt update
sudo apt install git
Mac (Homebrew)
brew install git
Windows 下载 Git 官方安装包 并安装。
配置 Git
安装完成后,设置用户名和邮箱:
git config --global user.name "你的名字"
git config --global user.email "你的邮箱"
检查配置:
git config --list
Git 基本操作
创建 Git 仓库
mkdir my_project # 创建新文件夹
cd my_project # 进入项目目录
git init # 初始化 Git 仓库
运行 git init
后,目录下会生成 .git
文件夹(隐藏文件),表示该目录已经是一个 Git 仓库。
添加文件并提交
touch file.txt # 创建新文件
echo "Hello Git" > file.txt # 写入内容
git status # 查看当前状态
git add file.txt # 添加到暂存区
git commit -m "第一次提交" # 提交更改
Git 运行机制
-
git add
把文件添加到 暂存区(Staging Area) -
git commit
把暂存区的内容提交到 本地仓库(Local Repository)
查看提交历史
git log # 查看提交历史
git log --oneline # 简洁模式
git log --graph --all # 以图形方式查看
分支管理
创建和切换分支
git branch feature # 创建新分支
git checkout feature # 切换到新分支
git switch feature # (新方法)切换到新分支
合并分支
git checkout main
git merge feature # 将 feature 合并到 main
删除分支
git branch -d feature
远程仓库(GitHub / GitLab)
关联远程仓库
git remote add origin https://github.com/user/repo.git
git push -u origin main # 推送到远程仓库
拉取远程代码
git pull origin main # 获取最新代码
练习任务
✅ 1. 初始化一个 Git 仓库(git init
)
✅ 2. 创建文件并提交(git add
+ git commit
)
✅ 3. 创建一个分支并切换(git branch
+ git checkout
)
✅ 4. 把代码推送到 GitHub(git push
)
4. 深入理解汇编语言的 CPU 指令集
1. 什么是 CPU 指令集?
CPU 指令集(Instruction Set Architecture, ISA) 是 CPU 能够理解和执行的指令集合。不同 CPU 可能使用不同的指令集,例如:
体系架构 | 常见 CPU | 指令集 |
---|---|---|
x86 / x86-64 | Intel, AMD | x86, x86-64 (Intel/AMD64) |
ARM | Apple M1/M2, Qualcomm Snapdragon | ARMv8, ARMv9 |
RISC-V | SiFive, 未来自研 CPU | RISC-V |
指令集决定了汇编语言的语法,同一个操作在不同架构上的写法可能不同。
2. CPU 的基本组成
CPU 的核心部件包括:
-
寄存器(Registers):存储数据和地址,CPU 直接访问的存储单元
-
算术逻辑单元(ALU):执行算术和逻辑运算
-
控制单元(CU):解码指令,控制数据流
-
总线(Bus):连接 CPU、内存和外设
🔹 x86 寄存器
64 位寄存器 | 32 位 | 16 位 | 8 位 | 用途 |
---|---|---|---|---|
RAX | EAX | AX | AL / AH | 累加寄存器(算术运算) |
RBX | EBX | BX | BL / BH | 基址寄存器 |
RCX | ECX | CX | CL / CH | 计数器(循环/位移) |
RDX | EDX | DX | DL / DH | 数据寄存器 |
RSP | ESP | SP | - | 栈指针 |
RBP | EBP | BP | - | 栈基址 |
RSI | ESI | SI | - | 源索引寄存器 |
RDI | EDI | DI | - | 目标索引寄存器 |
💡 64 位模式下,额外提供 R8-R15 寄存器。
3. 指令格式
大多数指令格式如下:
指令 操作数1, 操作数2
-
操作数可以是 寄存器、内存地址、立即数
-
x86 格式(AT&T 语法):
movl %eax, %ebx
(源 -> 目标
) -
Intel 语法(常用):
mov eax, ebx
(源 -> 目标
)
4. x86 常见指令
✅ 数据传输指令
指令 | 说明 |
---|---|
MOV dest, src | 复制数据 |
LEA dest, src | 取地址 |
PUSH src | 压栈 |
POP dest | 出栈 |
示例:
mov eax, 5 ; 把 5 赋值给 EAX
mov ebx, eax ; 把 EAX 的值复制到 EBX
算术指令
指令 | 说明 |
---|---|
ADD dest, src | 加法 |
SUB dest, src | 减法 |
MUL src | 乘法(无符号) |
IMUL src | 乘法(有符号) |
DIV src | 除法(无符号) |
IDIV src | 除法(有符号) |
示例:
mov eax, 10 add eax, 5 ;
eax = eax + 5 sub eax, 3 ;
eax = eax - 3
逻辑运算
指令 | 说明 |
---|---|
AND dest, src | 按位与 |
OR dest, src | 按位或 |
XOR dest, src | 按位异或 |
NOT dest | 取反 |
SHL dest, n | 左移 n 位 |
SHR dest, n | 右移 n 位 |
示例:
mov eax, 0b1100
and eax, 0b1010 ; 结果 = 0b1000
比较与跳转
指令 | 说明 |
---|---|
CMP op1, op2 | 比较 op1 和 op2 |
JE label | 等于跳转 |
JNE label | 不等跳转 |
JG label | 大于跳转 |
JL label | 小于跳转 |
JMP label | 无条件跳转 |
示例:
mov eax, 5
cmp eax, 10
jl less_than_10 ; 如果 eax < 10,跳转
函数调用
指令 | 说明 |
---|---|
CALL func | 调用函数 |
RET | 返回 |
示例:
call my_function
ret
RISC-V 和 ARM 对比
操作 | x86 | ARM | RISC-V |
---|---|---|---|
传输 | mov eax, ebx | mov r0, r1 | mv x1, x2 |
加法 | add eax, ebx | add r0, r1, r2 | add x1, x2, x3 |
跳转 | jmp label | b label | j label |
函数 | call func | bl func | jal x1, func |
练习:编写一个简单的汇编程序
section .data
msg db "Hello, world!", 0 ; 字符串
section .text
global _start
_start:
mov edx, 13 ; 输出长度
mov ecx, msg ; 指向字符串
mov ebx, 1 ; 标准输出
mov eax, 4 ; syscall: sys_write
int 0x80 ; 触发系统调用
mov eax, 1 ; syscall: sys_exit
xor ebx, ebx ; 退出代码 0
int 0x80
运行方法
-
安装 NASM:
sudo apt install nasm
-
编译:
nasm -f elf32 hello.asm
-
生成可执行文件:
ld -m elf_i386 -o hello hello.o
-
运行:
./hello
你可以做什么?
✅ 1. 练习写一些基本指令(MOV, ADD, CMP, JMP)
✅ 2. 用 gdb
调试一个汇编程序
✅ 3. 尝试编写简单的 RISC-V 或 ARM 汇编
4.2 区分并解读ARM 和 RISC-V
1. ARM vs. RISC-V 概述
特性 | ARM | RISC-V |
---|---|---|
架构类型 | RISC(精简指令集) | RISC(精简指令集) |
开发模式 | 封闭商业授权(需付费) | 开源(免费使用) |
指令集 | 复杂,历史包袱较重 | 简洁、模块化 |
市场占有率 | 高(广泛用于手机、嵌入式设备) | 仍在增长(嵌入式、学术、未来芯片) |
性能优化 | 针对特定硬件优化,功耗低 | 设计简洁,易扩展 |
厂商 | Apple M1/M2/M3、Qualcomm、Broadcom | SiFive、NVIDIA、Intel(未来) |
应用领域 | 移动设备、嵌入式系统、服务器 | 开源硬件、学术研究、未来服务器 |
ARM 适合商用市场,RISC-V 更适合研究、定制芯片、国产化 CPU。
2. 指令集对比
(1)寄存器
-
ARM(AArch64,64 位):31 个通用寄存器(X0 - X30),加上 SP(栈指针)和 PC(程序计数器)。
-
RISC-V(RV64I):32 个通用寄存器(x0 - x31),x0 恒为
0
,x1
用作返回地址,x2
为栈指针。
寄存器 | ARM (AArch64) | RISC-V (RV64I) |
---|---|---|
返回值寄存器 | X0 | x10 (a0) |
参数传递寄存器 | X0 - X7 | x10 - x17 (a0 - a7) |
栈指针 | SP | x2 (sp) |
返回地址 | X30 (LR) | x1 (ra) |
(2)基本指令
操作 | ARM | RISC-V |
---|---|---|
数据传输 | MOV X0, X1 | ADD x10, x0, x0 (没有 MOV ,用 ADD 实现) |
加载/存储 | LDR X0, [X1] | LW x10, 0(x1) |
算术运算 | ADD X0, X1, X2 | ADD x10, x11, x12 |
逻辑运算 | AND X0, X1, X2 | AND x10, x11, x12 |
比较 & 跳转 | CMP X0, X1 B.EQ label | BEQ x10, x11, label |
函数调用 | BL function | JAL x1, function |
返回 | RET | JALR x0, x1, 0 |
💡 区别:
-
ARM 有
MOV
指令,RISC-V 没有,需要用ADD
代替。 -
ARM
LDR
直接加载数据,RISC-V 需要LW
(load word)。 -
RISC-V 所有运算都基于寄存器,没有
CMP
,而是SUB + 分支指令
。
3. ARM vs. RISC-V 示例代码
- ARM (AArch64)
.global _start
_start:
MOV X0, #42 // X0 = 42
MOV X1, #10 // X1 = 10
ADD X2, X0, X1 // X2 = X0 + X1
BL exit // 调用 exit
exit:
MOV X8, #93 // syscall exit
SVC 0
- RISC-V (RV64I)
.global _start
_start:
LI x10, 42 # x10 = 42
LI x11, 10 # x11 = 10
ADD x12, x10, x11 # x12 = x10 + x11
J exit # 跳转到 exit
exit:
LI a7, 93 # syscall exit
ECALL
主要区别:
-
ARM 直接使用
MOV
,RISC-V 需要LI
(Load Immediate)。 -
ARM 直接调用
BL
进入函数,RISC-V 用JAL
。 -
ARM
SVC 0
调用系统调用,RISC-V 用ECALL
。
4. ARM vs. RISC-V 的发展前景
对比 | ARM | RISC-V |
---|---|---|
市场份额 | 高,占主导 | 快速增长 |
开放性 | 封闭(需授权) | 开源(免费) |
生态系统 | 成熟(Android、iOS、嵌入式) | 正在完善(未来竞争力强) |
功耗优化 | 非常出色(Apple M 系列) | 理论上更好,但仍在优化 |
使用场景 | 移动设备、服务器、嵌入式 | 未来服务器、国产 CPU、物联网 |
5. 总结
✅ ARM:适用于 商业化市场,功耗优化极致,广泛用于手机、嵌入式。
✅ RISC-V:完全开源,未来有潜力取代 ARM,但生态系统仍在发展。
如果你想深入学习:
-
ARM 推荐:学习 AArch64 汇编(Apple M1/M2、树莓派)。
-
RISC-V 推荐:用 QEMU 模拟,或者试试 SiFive 开发板。
4.3 从ARM 和 RISC-V 的基础概念,逐步深入到汇编编程和架构优化
学习路线:
第一阶段:基础概念
✅ 1. 计算机架构基础
-
什么是 RISC(精简指令集) 和 CISC(复杂指令集)
-
ARM 和 RISC-V 的设计理念
-
指令流水线、寄存器、内存访问方式
✅ 2. ARM & RISC-V 指令集
-
了解寄存器(ARM 的 X0-X30,RISC-V 的 x0-x31)
-
基本数据传输(
MOV
、LW
、LDR
等) -
算术运算(
ADD
、SUB
等) -
逻辑运算(
AND
、OR
、XOR
等) -
分支与跳转(
JMP
、BEQ
、BL
等)
第二阶段:搭建开发环境
✅ 1. ARM 开发环境
-
在 Raspberry Pi(树莓派)或 QEMU 上运行 ARM 代码
-
使用 GNU
as
(汇编器) 编写 ARM 汇编 -
ARM 64-bit (AArch64) vs ARM 32-bit (ARMv7)
✅ 2. RISC-V 开发环境
-
使用 QEMU 模拟 RISC-V
-
使用 riscv-gcc 编写汇编代码
-
了解 RISC-V 的模块化扩展(
RV32I
、RV64GC
)
第三阶段:深入汇编编程
✅ 1. 编写简单程序
-
"Hello, World!" 汇编实现(ARM & RISC-V)
-
计算加法、乘法等基本运算
-
使用 函数调用(CALL/JAL) 和 系统调用(SVC/ECALL)
✅ 2. 代码调试
-
用 GDB(GNU Debugger) 调试 ARM & RISC-V 汇编
-
学习 寄存器、内存管理、堆栈操作
-
分析 函数调用栈
第四阶段:深入体系架构
✅ 1. ARM 高级特性
-
Thumb 模式(ARM 32-bit 低功耗指令)
-
NEON(SIMD) 向量计算
-
TrustZone 安全架构
✅ 2. RISC-V 扩展
-
RV64GC 标准指令集
-
压缩指令(C-extension)
-
向量计算(V-extension)
架构原理
RISC(精简指令集) vs. CISC(复杂指令集)
RISC(Reduced Instruction Set Computer)
-
指令长度固定(如 RISC-V 32 位指令)
-
只使用 Load/Store 访问内存(所有运算都基于寄存器)
-
指令集精简,减少硬件复杂性,提升执行效率
-
流水线执行优化(提高指令并行度)
CISC(Complex Instruction Set Computer)
-
指令长度可变(如 x86 指令有 1-15 字节)
-
支持内存直接操作(可对内存数据直接算术运算)
-
指令复杂,执行周期长(但可以减少指令数量)
-
适用于高性能计算,但功耗较大
💡 ARM 和 RISC-V 都属于 RISC 体系,相比 x86(CISC)更节能、更易于硬件优化。
ARM 架构
🔹 ARM 设计特点
-
AArch64(ARM 64-bit):现代主流架构(Apple M 系列、Android 手机等)
-
AArch32(ARM 32-bit):老架构(ARMv7,如 Raspberry Pi 1/2)
-
寄存器:31 个通用寄存器(X0-X30),SP(栈指针),PC(程序计数器)
-
支持 Thumb 低功耗模式(部分 ARM 处理器)
-
广泛用于移动设备、嵌入式系统
🔹 ARM 典型指令
-
LDR X0, [X1]
// 从内存加载数据到 X0 -
STR X0, [X1]
// 将 X0 存入 X1 指向的内存 -
ADD X0, X1, X2
// X0 = X1 + X2 -
BL function
// 调用函数 -
RET
// 返回
RISC-V 架构
🔹 RISC-V 设计特点
-
完全开源,可定制(不同于 ARM 的授权模式)
-
模块化指令集(基础指令
RV32I
、RV64I
,可扩展M
乘除、C
压缩、V
向量等) -
寄存器:32 个通用寄存器(x0-x31),x0 恒等于 0
-
适用于芯片设计、学术研究、物联网
🔹 RISC-V 典型指令
-
LW x10, 0(x1)
// 从内存加载数据到 x10 -
SW x10, 0(x1)
// 将 x10 存入 x1 指向的内存 -
ADD x10, x11, x12
// x10 = x11 + x12 -
JAL x1, function
// 调用函数 -
JALR x0, x1, 0
// 返回
ARM vs. RISC-V 对比
特性 | ARM | RISC-V |
---|---|---|
架构类型 | RISC | RISC |
授权模式 | 封闭授权(需付费) | 完全开源(免费使用) |
指令集 | 复杂(历史包袱较重) | 精简,模块化 |
功耗优化 | 极致优化(Apple M1/M2) | 理论上更优,但仍需优化 |
应用场景 | 移动设备、嵌入式、服务器 | 芯片研究、物联网、未来服务器 |
下一步学习
✅ 了解 ARM & RISC-V 指令集 ✅ 研究 寄存器与内存访问 ✅ 搭建 ARM & RISC-V 开发环境(QEMU、Raspberry Pi、SiFive)
4.4 ARM 和 RISC-V 的指令集
1. ARM & RISC-V 指令集概述
对比项 | ARM (AArch64, 64-bit) | RISC-V (RV64I, 64-bit) |
---|---|---|
指令长度 | 固定 32 位(支持 16 位 Thumb 指令) | 固定 32 位(支持 16 位压缩指令 C-extension) |
寄存器 | X0 - X30(31 个通用寄存器) | x0 - x31(32 个通用寄存器) |
栈指针 | SP(Stack Pointer) | x2(sp) |
程序计数器 | PC(Program Counter) | PC(Program Counter) |
内存访问 | LDR/STR(Load/Store) | LW/SW(Load Word / Store Word) |
跳转/调用 | BL(Branch & Link)、RET | JAL(Jump and Link)、JALR |
运算指令 | ADD、SUB、MUL、AND、ORR、EOR | ADD、SUB、MUL、AND、OR、XOR |
系统调用 | SVC(Supervisor Call) | ECALL(Environment Call) |
2. ARM 指令集
🔹 2.1 数据传输
-
LDR X0, [X1]
// 从内存加载数据到 X0 -
STR X0, [X1]
// 将 X0 存入 X1 指向的内存 -
MOV X0, X1
// 将 X1 的值复制到 X0
🔹 2.2 算术运算
-
ADD X0, X1, X2
// X0 = X1 + X2 -
SUB X0, X1, X2
// X0 = X1 - X2 -
MUL X0, X1, X2
// X0 = X1 * X2 -
SDIV X0, X1, X2
// X0 = X1 / X2(整数除法)
🔹 2.3 逻辑运算
-
AND X0, X1, X2
// X0 = X1 & X2 -
ORR X0, X1, X2
// X0 = X1 | X2 -
EOR X0, X1, X2
// X0 = X1 ^ X2 -
LSL X0, X1, #3
// X0 = X1 << 3(左移 3 位) -
LSR X0, X1, #3
// X0 = X1 >> 3(右移 3 位)
🔹 2.4 条件分支
-
CMP X0, X1
// 比较 X0 和 X1 -
B.EQ label
// 如果相等,则跳转到 label -
B.NE label
// 如果不相等,则跳转到 label -
B.GT label
// 如果 X0 > X1,则跳转 -
BL function
// 调用 function -
RET
// 返回
3. RISC-V 指令集
🔹 3.1 数据传输
-
LW x10, 0(x1)
// 从内存加载数据到 x10 -
SW x10, 0(x1)
// 将 x10 存入 x1 指向的内存 -
MV x10, x11
// 将 x11 复制到 x10(MOV
在 RISC-V 中是ADD
的别名)
🔹 3.2 算术运算
-
ADD x10, x11, x12
// x10 = x11 + x12 -
SUB x10, x11, x12
// x10 = x11 - x12 -
MUL x10, x11, x12
// x10 = x11 * x12 -
DIV x10, x11, x12
// x10 = x11 / x12(整数除法)
🔹 3.3 逻辑运算
-
AND x10, x11, x12
// x10 = x11 & x12 -
OR x10, x11, x12
// x10 = x11 | x12 -
XOR x10, x11, x12
// x10 = x11 ^ x12 -
SLL x10, x11, x12
// x10 = x11 << x12(左移) -
SRL x10, x11, x12
// x10 = x11 >> x12(右移)
🔹 3.4 条件分支
-
BEQ x10, x11, label
// 如果 x10 == x11,跳转 -
BNE x10, x11, label
// 如果 x10 != x11,跳转 -
BLT x10, x11, label
// 如果 x10 < x11,跳转 -
BGE x10, x11, label
// 如果 x10 >= x11,跳转 -
JAL x1, function
// 调用 function -
JALR x0, x1, 0
// 返回
4. ARM vs. RISC-V 指令示例
🔹 ARM (AArch64)
.global _start
_start:
MOV X0, #42 // X0 = 42
MOV X1, #10 // X1 = 10
ADD X2, X0, X1 // X2 = X0 + X1
BL exit // 调用 exit
exit:
MOV X8, #93 // syscall exit
SVC 0
🔹 RISC-V (RV64I)
.global _start _start:LI x10, 42 # x10 = 42LI x11, 10 # x11 = 10ADD x12, x10, x11 # x12 = x10 + x11J exit # 跳转到 exit exit:LI a7, 93 # syscall exitECALL
主要区别:
-
ARM 直接使用
MOV
指令,RISC-V 需要LI
(Load Immediate) -
ARM 直接调用
BL
,RISC-V 需要JAL
-
ARM 使用
SVC 0
,RISC-V 使用ECALL
进行系统调用
4.5 编写 ARM & RISC-V 汇编代码
1. 编写 ARM 汇编代码(AArch64)
🔹 1.1 "Hello, World!"
.global _start
.section .data
message: .asciz "Hello, World!\n"
.section .text
_start:
MOV X0, #1 // 文件描述符 1 (stdout)
ADR X1, message // 消息地址
MOV X2, #14 // 消息长度
MOV X8, #64 // syscall write
SVC 0
MOV X8, #93 // syscall exit
MOV X0, #0 // 退出码 0
SVC 0
说明
-
MOV X0, #1
设置标准输出 -
ADR X1, message
加载字符串地址 -
MOV X8, #64
表示write
系统调用 -
SVC 0
触发系统调用
1.2 简单的加法
.global _start
_start:
MOV X0, #10 // X0 = 10
MOV X1, #20 // X1 = 20
ADD X2, X0, X1 // X2 = X0 + X1
MOV X8, #93 // syscall exit
MOV X0, #0
SVC 0
说明
-
MOV
指令用于加载立即数 -
ADD X2, X0, X1
计算 X0 + X1
1.3 条件判断
.global _start
_start:
MOV X0, #5
MOV X1, #10
CMP X0, X1
B.GE greater_or_equal
MOV X2, #0 // X0 < X1 时执行
B exit
greater_or_equal:
MOV X2, #1 // X0 >= X1 时执行
exit:
MOV X8, #93
SVC 0
说明
-
CMP X0, X1
进行比较 -
B.GE
进行条件跳转
2. 编写 RISC-V 汇编代码(RV64I)
🔹 2.1 "Hello, World!"
.global _start
.section .data
message: .asciz "Hello, World!\n"
.section .text
_start:
LI a0, 1 # 文件描述符 1 (stdout)
LA a1, message # 加载字符串地址
LI a2, 14 # 消息长度
LI a7, 64 # syscall write
ECALL
LI a7, 93 # syscall exit
LI a0, 0 # 退出码 0
ECALL
说明
-
LI
(Load Immediate)用于加载立即数 -
LA
(Load Address)用于加载地址 -
ECALL
触发系统调用
2.2 简单的加法
.global _start
_start:
LI x10, 10 # x10 = 10
LI x11, 20 # x11 = 20
ADD x12, x10, x11 # x12 = x10 + x11
LI a7, 93 # syscall exit
ECALL
说明
-
LI
加载数值 -
ADD
执行加法
2.3 条件判断
.global _start
_start:
LI x10, 5
LI x11, 10
BGE x10, x11, greater_or_equal
LI x12, 0 # x10 < x11 时执行
J exit
greater_or_equal:
LI x12, 1 # x10 >= x11 时执行
exit:
LI a7, 93
ECALL
说明
-
BGE x10, x11, label
进行条件跳转 -
J label
无条件跳转
3. 运行汇编代码
🔹 ARM(AArch64)
在 Linux 上安装 GCC
并运行:
aarch64-linux-gnu-as -o program.o program.s
aarch64-linux-gnu-ld -o program program.o
qemu-aarch64 ./program
🔹 RISC-V
安装 riscv64
交叉编译工具:
riscv64-linux-gnu-as -o program.o program.s
riscv64-linux-gnu-ld -o program program.o
qemu-riscv64 ./program
4.6 搭建 ARM & RISC-V 开发环境
1. 运行 ARM 指令
🔹 1.1 编写 ARM 汇编
创建文件 arm_test.s
:
.global _start
_start:
MOV X0, #42 // X0 = 42
MOV X8, #93 // syscall exit
SVC 0 // 执行系统调用
1.2 编译 & 运行
aarch64-linux-gnu-as -o arm_test.o arm_test.s # 汇编
aarch64-linux-gnu-ld -o arm_test arm_test.o # 链接
qemu-aarch64 ./arm_test # 运行
如果成功,程序会 返回状态码 42,可以用 $?
检查:
echo $?
2. 运行 RISC-V 指令
🔹 2.1 编写 RISC-V 汇编
创建文件 riscv_test.s
:
.global _start
_start:
LI a0, 42 # a0 = 42
LI a7, 93 # syscall exit
ECALL # 执行系统调用
2.2 编译 & 运行
riscv64-linux-gnu-as -o riscv_test.o riscv_test.s # 汇编
riscv64-linux-gnu-ld -o riscv_test riscv_test.o # 链接
qemu-riscv64 ./riscv_test # 运行
同样,可以用 $?
检查返回值:
echo $?
3. 在 QEMU 启动完整 Linux
🔹 3.1 运行 ARM Linux
qemu-aarch64 -L /usr/aarch64-linux-gnu ./arm_test
-L /usr/aarch64-linux-gnu
指定 QEMU 运行所需的 ARM 共享库。
🔹 3.2 运行 RISC-V Linux
qemu-riscv64 -L /usr/riscv64-linux-gnu ./riscv_test
4. 进入 QEMU 交互模式
可以运行 QEMU 并进入 GDB 调试模式:
qemu-aarch64 -g 1234 ./arm_test
然后在另一个终端启动 GDB:
gdb-multiarch -q -ex "target remote :1234"