自定义汇编语言(Custom Assembly Language) 和 Unix Git
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"
相关文章:
自定义汇编语言(Custom Assembly Language) 和 Unix Git
1. 什么是自定义汇编语言(Custom Assembly Language)? 汇编语言(Assembly Language)是一种低级编程语言,它直接与 CPU 指令集(Instruction Set Architecture, ISA)对应,…...
Python菜鸟教程(小程序)
目录 一.简易计算器 二.学生成绩分级 三.密码设置 四.作业选择 点赞收藏,评论支持 一.简易计算器 print(-------使用的运算符-------\n) print(1.加号) print(2.减号) print(3.乘号) print(4.除号) Aint(input(请输入第一个数: )) Bint(input(请输入第二个数: )) Fi…...
2011-2019年各省地方财政金融监管支出数据
2011-2019年各省地方财政金融监管支出数据 1、时间:2007-2019年 2、来源:国家统计局、统计年鉴 3、指标:行政区划代码、地区、年份、地方财政金融监管支出 4、范围:31省 5、指标说明:地方财政在金融监管方面的支出…...
Java大厂面试题 -- JVM 优化进阶之路:从原理到实战的深度剖析(2)
最近佳作推荐: Java大厂面试题 – 深度揭秘 JVM 优化:六道面试题与行业巨头实战解析(1)(New) 开源架构与人工智能的融合:开启技术新纪元(New) 开源架构的自动化测试策略优…...
SQL LIKE 语句详解
SQL LIKE 语句详解 引言 SQL(Structured Query Language)是用于管理关系数据库的标准语言。在SQL中,LIKE 语句是一种常用的字符串匹配操作符,用于在查询中搜索包含特定模式的字符串。本文将详细介绍 LIKE 语句的用法、规则以及注意事项。 一、什么是 LIKE 语句? LIKE …...
现代Web应用中的时光机器:深入解析撤销/重做功能的艺术与科学
引言:数字世界的安全网 在现实世界中,我们拥有橡皮擦、撤销键和后悔药(比喻意义上)。数字世界同样需要这样的安全保障。研究表明: **85%**的用户会在完成复杂表单时犯至少一个错误 提供撤销功能的界面可将用户满意度…...
存储引擎 / 事务 / 索引
1. 存储引擎 MySQL 中特有的术语。 (Oracle 有,但不叫这个名字) 是一种表存储 / 组织数据的方式 不同的存储引擎,表存储数据的方式不同 1.1 查看存储引擎 命令: show engines \g(或大写:G…...
Go语言-初学者日记(八):构建、部署与 Docker 化
🧱 一、go build:最基础的构建方式 Go 的构建工具链是出了名的轻量、简洁,直接用 go build 就能把项目编译成二进制文件。 ✅ 构建当前项目 go build -o myapp-o myapp 指定输出文件名默认会构建当前目录下的 main.go 或 package main &a…...
【ESP32】ESP32物联网应用:MQTT控制与状态监测
ESP32物联网应用:MQTT控制与状态监测 引言 在物联网时代,远程监测和控制设备已经成为现实生活中常见的需求。本文将介绍如何使用ESP32微控制器配合MQTT协议,实现一个简单而强大的物联网应用:远程状态监测和设备控制。我们将以巴…...
RabbitMQ运维
RabbitMQ运维 一.集群1.简单介绍2.集群的作用 二.搭建集群1.多机多节点搭建步骤 2.单机单节点搭建步骤 3.宕机演示 三.仲裁队列1.简单介绍2.Raft协议Raft基本概念主节点选举选举过程 3.仲裁队列的使用 四.HAProxy负载均衡1.安装HAProxy2.HAProxy的使用 一.集群 1.简单介绍 Ra…...
Ansible 实战:Roles,运维的 “魔法函数”
一、介绍 你现在已经学过tasks和handlers,那么,最好的playbook组织方式是什么呢?答案很简单:使用roles!roles基于一种已知的文件结构,能够自动加载特定的vars_files、tasks以及handlers。通过roles对内容进…...
CVAT安装和使用(Windows)
必要组件安装 WSL2 Docker Git Chrome Install WSL2 (Windows subsystem for Linux) refer to this official guide. WSL2 requires Windows 10, version 2004 or higher. After installing WSL2, install a Linux Distribution of your choice. 安装 WSL2(适用…...
Spring 中的 bean 生命周期
🌱 一、什么是 Bean 生命周期? 在 Spring 容器中,一个 Bean 从“创建 → 初始化 → 使用 → 销毁”,经历了完整的生命周期。 Spring 提供了 多个扩展点 让你可以在这些阶段做事情,比如注入资源、日志记录、连接资源、清…...
关于JVM和OS中的指令重排以及JIT优化
关于JVM和OS中的指令重排以及JIT优化 前言: 这东西应该很重要才对,可是大多数博客都是以讹传讹,全是错误,尤其是JVM会对字节码进行重排都出来了,明明自己测一测就出来的东西,写出来误人子弟… 研究了两天&…...
微软推出首款量子计算芯片Majorana 1
全球首款拓扑架构量子芯片问世,2025年2月20日,经过近20年研究,微软推出了首款量子计算芯片Majorana 1,其宣传视频如本文末尾所示。 微软表示,开发Majorana 1需要创造一种全新的物质状态,即所谓的“拓扑体”…...
数组练习题总结
一、求出数组中的最大值let arr [1, 2, 5, 7];let max 0;for (i 0; i < arr.length; i) {// console.log(max);if (max < arr[i]) {max arr[i];}}console.log(max); 首先生成一个数组,设一个变量为保存最大值,写一个循环,在循环里写…...
Kotlin 中的 `reified` 关键字全解析:保留类型信息 + 优化高阶函数的双重魔法
在使用 Kotlin 编写泛型函数时,你是否遇到过这样的尴尬:你想判断某个对象是不是泛型类型 T,结果却发现代码根本编译不过?这是因为 Kotlin 和 Java 一样,泛型在运行时会被类型擦除。 为了解决这个问题,Kotl…...
在CPU服务器上部署Ollama和Dify的过程记录
在本指南中,我将详细介绍如何在CPU服务器上安装和配置Ollama模型服务和Dify平台,以及如何利用Docker实现这些服务的高效部署和迁移。本文分为三大部分:Ollama部署、Dify环境配置和Docker环境管理,适合需要在本地或私有环境中运行A…...
【计网】TCP 协议详解 与 常见面试题
三次握手、四次挥手的常见面试题 不用死记,只需要清楚三次握手,四次挥手的流程,回答的时候心里要记住,假设网络是不可靠的 问题(1):为什么关闭连接时需要四次挥手,而建立连接却只要三次握手? 关…...
Java 基础-31-枚举-认识枚举
在Java编程语言中,枚举(Enum)是一种特殊的类,它允许一组固定的常量。它们非常适合用来表示一组固定的值,比如星期几、季节、颜色等。枚举自Java 5开始引入,为定义常量提供了一种更强大和方便的方式。本文将…...
7.4 SVD 的几何背景
一、SVD 的几何解释 SVD 将矩阵分解成三个矩阵的乘积: ( 正交矩阵 ) ( 对角矩阵 ) ( 正交矩阵 ) (\pmb{正交矩阵})\times(\pmb{对角矩阵})(\pmb{正交矩阵}) (正交矩阵)(对角矩阵)(正交矩阵),用几何语言表述其几何背景: ( 旋转 ) ( 伸缩 )…...
低延迟云网络的核心技术
低延迟云网络通过架构优化、协议创新、硬件加速等多维度技术手段,将数据传输延迟降低至毫秒级甚至微秒级。 1. 网络架构优化 1.1 扁平化网络Leaf-Spine 架构 减少网络层级,缩短数据转发路径(如数据中心内部一跳可达)。 扁平化网络Leaf-Spine(叶子-脊椎)架构是一种现代…...
C++的多态-上
目录 多态的概念 多态的定义及实现 1.虚函数 2. 多态的实现 2.1.多态构成条件 2.2.虚函数重写的两个例外 (1)协变(基类与派生类虚函数返回值类型不同) (2)析构函数的重写(基类与派生类析构函数的名字不同) 2.3.多态的实现 2.4.多态在析构函数中的应用 2.5.多态构成条…...
内存与显存:从同根生到殊途异路的科技演进
在现代计算机的世界里,内存和显存是两个不可或缺的硬件组件。它们看似功能相近,却在发展历程中逐渐分道扬镳,各自服务于不同的计算需求。今天,我们将从一根内存条和一块显卡入手,深入探讨内存与显存的异同,…...
手搓多模态-04 归一化介绍
在机器学习中,归一化是一个非常重要的工具,它能帮助我们加速训练的速度。在我们前面的SiglipVisionTransformer 中,也有用到归一化层,如下代码所示: class SiglipVisionTransformer(nn.Module): ##视觉模型的第二层&am…...
【C++】第八节—string类(上)——详解+代码示例
hello,又见面了! 云边有个稻草人-CSDN博客 C_云边有个稻草人的博客-CSDN博客——C专栏(质量分高达97!) 菜鸟进化中。。。 目录 一、为什么要学习string类? 1.1 C语言中的字符串 1.2 面试题(暂不做讲解) …...
Java 数组与 ArrayList 核心区别解析:从源码到实战!!!
🌟 Java 数组与 ArrayList 核心区别解析:从源码到实战 💡 Java 开发者必读! 数组(Array)和 ArrayList 是 Java 中最常用的数据存储结构,但它们的底层设计、性能表现和适用场景差异显著。本文通…...
【易飞】易飞批量选择品号处理方法,工作效率提升300%
开窗选择品号方式要么手动输入,要么以什么开头、包含、从A物料到B物料查询后返回的有规律的品号。对于没有规律且大量品号的处理方式是否有便捷的方法呢? 尤其在通常在查询多阶材料清单,查询库存明细表,整批变更元件等如品号无规律情况下,只能一个个选择,无法通过EXCEL方…...
【最新版】啦啦外卖v64系统独立版源码+全部小程序APP端+安装教程
一.系统介绍 啦啦外卖跑腿平台独立版,使用的都知道该系统功能非常强大,应该说是目前外卖平台功能最全的一套系统。主要是功能非常多,拿来即用,包括客户端小程序、配送端小程序、商户端小程序,还有对应四个端的APP源码…...
iproute2 工具集使用详解
目录 一、iproute2 核心命令:ip二、常用功能详解1. 管理网络接口(link 对象)2. 管理 IP 地址(address 对象)3. 管理路由表(route 对象)4. 管理 ARP 和邻居缓存(neigh 对象࿰…...
