ARM笔记

ARM笔记

1.查看进程
ps aux查看系统上的所有进程
ps axjf 显示完整的进程树
htop -u username(用户名) 查看特定用户创建的进程
atop是交互式系统性能监控工具 安装完后直接输入atop即可启动默认每10s刷新一次数据,也可以指定时间atop 5
top -H -p<pid> 查看程序内部线程

2.动态跟踪特定进程调用了那些系统调用
sudo strace -c -p 12(进程ID)

3.查看当前系统使用的页面大小
getconf PAGESIZE

4.查看elf文件中各节的内容
readelf -IW /usr/bin/cat 查看cat程序的程序头

5.取消随机化
在gdb调试中设置 set disable-randomiztion on/off
或者修改/proc/sys/kernel/randomize_va_space的值 0不随机化 1随机化 2完全随机化
sudo sh -c "echo 0" > /proc/sys/kernel/randomize_va_space"

6.ARM A64一些要点说明
A64有31个64位的通用寄存器
X0-X7是参数寄存器,用来传递参数并返回结果
X8用于传递间接结果的地址位置
X9-X15是调用者保存的临时寄存器,用于在调用另一个函数时保存数值.受影响的寄存器被保存在调用函数的栈帧中,允许子程序修改这些寄存器
X16-X18是子程序内调用临时寄存器,可以用作子程序调用之间的立即数的临时寄存器
X19-X28是被调用者保存的寄存器,他们被保存在被调用子程序的栈帧中,允许子程序修改这些寄存器,但也要求在返回给调用者之前恢复这些寄存器
X29用作栈帧指针(Frame Pointer,FP),用于跟踪栈帧
X30用作连接寄存器(Link Register,LR),用于保存函数的返回地址

7.A64专用寄存器
寄存器 名称 寄存器宽度
PC 程序计数器 64位
SP 栈指针寄存器 64位
WSP 栈指针寄存器 32位
XZR 零寄存器 64位
WZR 零寄存器 32位
LR(X30) 链接寄存器 64位
ELR 异常链接寄存器 64位
PSTATE 程序状态寄存器 64位 标志位NZCV N(操作结果为负时被设置) Z(操作结果为零) C(操作产生了进位) V(操作产生了有符号溢出)
SPSR_ELx 给定异常级别的保存进程状态寄存器 32位

8.数据处理指令
add x0,x1,x2; x0=x1+x2
adds x0,x1,x2; x0=x1+x2 and set flags
A32指令允许使用以下元操作数形式
寄存器形式 add r0,r0,r1
常量立即数形式 add r0,r0,#100
移位寄存器形式 add r0,r0,r1,LSL #1 r0=r0+(r1<<1)
寄存器-移位寄存器形式 add r0,r0,r1,LSL r2 r0=r0+(r1<<r2)
扩展寄存器形式 支持的扩展类型:UXTB, UXTH, UXTW, UXTX (零扩展), SXTB, SXTH, SXTW, SXTX (符号扩展)。
lsl r0,r1,#2; r0=r1<<2
A64指令集支持四种基本类型的位移操作
逻辑左移(Logical Shift Left, LSL)
逻辑右移(Logical Shift Right, LSR)
算数右移(Arithmetic Shift Right, ASR)符号位不动
循环右移(ROTATE Right,ROR) 会帮移出的部分添加到移入的里面
位域移动
BFM Xd,Xn,#r(宽度),#s(目标位域LSB的位数
SBFM UBFM
指令 别名语法 实现方式
8到64位符号扩展 SXTB Xd,Wn SBFM Xd,Xn,#0,#7
16到64位符号扩展 SXTH Xd,Wn SBFM Xd,Xn,#0,#15
32到64位符号扩展 SXTW Xd,Wn SBFM Xd,Xn,#0,#31
8到64位零扩展 UXTB Xd,Wn UBFM Xd,Xn,#0,#7
16到64位零号扩展 UXTH Xd,Wn UBFM Xd,Xn,#0,#15
32到64位零号扩展 UXTW Xd,Wn UBFM Xd,Xn,#0,#31

9.内存访问指令
LDR R0,[R1] 加载寄存器 将R1内存中的值加载到R0
STR R0,[R1] 存储寄存器 将R0中保存的32位值存储到从基址寄存器R1获得的地址中
寻址模式
基地址寄存器直接寻址模式 LDR Rt,[Rn]
偏移寻址(基址加偏移量) LDR Rt,[Rn,<offset>] 不会更新Rn的值
前索引寻址 LDR Rt,[Rn,<offset>] 会先更新更新Rn的值
后索引寻址 LDR Rt,[Rn],<offset> 先加载数据 后Rn=Rn+offset
字面值寻址(PC相对寻址) LDR Rt,label
加载寄存器 LDUR(未缩放,支持1字节偏移和负数,偏移范围-256-255) LDR(缩放,0-4095,偏移量在A64下必须是8的倍数,A32下必须是4的倍数)
加载字节 LDURB(未缩放,,偏移范围-256-255) LDRB(缩放,0-4095)
加载有符号字节 LDURSB(未缩放,,偏移范围-256-255) LDRSB(缩放,0-4095)
加载有符号半字 LDURSH(未缩放,,偏移范围-256-255) LDRSB(缩放,0-4095)
加载有符号字 LDURSW(未缩放,,偏移范围-256-255) LDRSB(缩放,0-4095)
存储加载器 STUR STR
存储字节 STURB STRB
存储半字 STURH STRH
多重加载 LDM Rn{!},<registers> LDM sp,{r1,r2,r3} 寄存器需要按顺序,要不会提示警告自动排列,导致使用时错位 将sp指向的值一次加载到r1,r2,r3里面 最多16个
LDP X1,X2,[X0] 成对参数必须两个
多重存储 STM Rn{!},<registers> LDM sp,{r1,r2,r3}
STP X1,X2,[X0] 成对参数必须两个
递增后寻址 LDMIA 先赋值后增加指针
递增前寻址 LDMIB 先增加指针位置后赋值
递减后寻址 LDMDA
递减前寻址 LDADB

10.条件执行
A32条件码 Arm定义了16个4位条件码,这些条件码允许指令基于PSTATE的NZCV标志的状态有条件地执行。
值 条件码 语义(整数运算) 条件标志
0000 EQ 相等 Z==1
0001 NE 不相等 Z==0
0010 CS/HS 进位设置 C==1
0011 CC/LO 进位清楚 C==0
0100 MI 负数 N==1
0101 PL 正或零 N==0
0110 VS 溢出 V==1
0111 VC 无溢出 V==0
1000 HI 无符号大于 C==1 && Z==0
1001 LS 无符号小于或等于 !(C==1&&Z==0)
1010 GE 有符号大于或等于 N==V
1011 LT 有符号小于或等于 N!=V
1100 GT 有符号大于 Z==0&&N==V
1101 LE 有符号小于或等于 !(Z==0&&N==V)
1110 AL 始终(无条件) Any
1111 NV 无效 Any
条件指令 编写条件指令只需要将条件码直接附加到指令的末尾 如果条件码判断结果为真,则执行指令
IT指令
cmp r0,r1
itete EQ
addeq r0,r1,r2 ;use base cond(EQ)
andne r0,r0,#0xfff ; e:use negation(NE)
orreq r0,r0,#0xfff ; t:use cond(EQ)
addne r0,r0,#1 ; e:use negation(NE)
对应的逻辑伪代码
if(r0==r1){
ro=(r1+r2)|0xfff;
}else{
r0=(r0&0xfff)+1;
}
A64下条件选择指令
指令名称 指令语法 满足条件时的操作 不满足条件时的操作
条件选择 CSEL Xd,Xn,Xm,cond Xd=Xn Xd=Xm
条件选择自增 CSINC Xd,Xn,Xm,cond Xd=Xn Xd=Xm+1
条件选择倒置 CSINV Xd,Xn,Xm,cond Xd=Xn Xd=NOT(Xm)
条件选择取负 CSNEG Xd,Xn,Xm,cond Xd=Xn Xd=-Xm
条件设置 CSET Xd,cond Xd=1 Xd=0
条件设置掩码 CSETM Xd,cond Xd=(all ones) Xd=0
条件自增 CINC Xd,Xn,cond Xd=Xn+1 Xd=Xn
条件倒置 CINV Xd,Xn,cond Xd=NOT(Xn) Xd=Xn
条件取负 CNEG Xd,Xn,cond Xd=-Xn Xd=Xn
例子:
CMP w0,w1
CSEL w0,w1,zer,EQ
CCMP 条件比较指令 CCMP arg1,arg2,nzcv,cond
if(cond){
PSTATE.NZCV=CMP(arg1,arg2);
}else{
PSTATE.NZCV=nzcv
}
{
w0==w1&&w2<w3
cmp w0,w1
ccmp w2,w3,0,EQ
blt _label
}
{
w0==w1||w2<w3
cmp w0,w1
ccmp w2,w3,8,NE
blt _label
}
CCMN 条件比较否定指令
if(cond){
PSTATE.NZCV=CMN(arg1,arg2);
}else{
PSTATE.NZCV=nzcv
}

11.控制流
直接分支指令
指令 语法
无条件跳转指令 B <label>
条件跳转指令 B.<cond> <label>
带连接程序的跳转指令 BL <label>
如果给定寄存器不为零,则跳转 CBNZ Wt|Xt, <label>
如果给定寄存器为零,则跳转 CBZ Wt|Xt, <label>
64位才有的
如果给定寄存器的特定位不为零,则跳转 TBNZ Wt|Xt,#imm,<label>
如果给定寄存器的特定位位零,则跳转 TBZ Wt|Xt,#imm,<label>
寄存器分支指令
AArch64:
语法 指令
BR Xn 跳转到寄存器保存的地址
BLR Xn 带连接程序的跳转指令,跳转地址为寄存器保存的地址
RET {Xn} 从子程序返回
AArch32:
语法 指令
BX{cond} Rm 跳转到寄存器保存的地址,可进行模式切换
BLX(COND} Rm 带连接程序的跳转指令,跳转地址为寄存器保存的地址,可进行模式切换
BXJ{COND} Rm 跳转到寄存器保存的地址,可进行模式切换(Jazelle)
TBB{cond} {Rn,Rm} 表跳转(字节偏移)
TBB{cond} [Rn,Rm,LSL #1}表跳转(半字偏移)
例子1:
cmp r0,#4
beq end AArch64是 b.eq end需要加.
...
end:
...
例子2:
int func(int a){
unsigned int score = a;
char grade;
switch(score){
case 9: grade='A';break;
case 8: grade='B';break;
case 7: grade='C';break;
case 6: grade='D';break;
default: grade='F';break;
}
return grade;
}
00000000<func>
subs r0,#6
cmp r0,#3
bhi.n la<func+0x1a>
tbb [pc,r0]
.short 0x0406
.short 0x0a02
movs r0,#66
bx lr
movs r0,#67
bx lr
movs r0,#68
bx lr
movs r0,#70
bx lr
movs r0,#65
bx lr

12.安装arm64虚拟环境
使用 VNC 替代本地窗口(最稳定,保底方案)
如果本地图形界面(GTK/SDL)始终报错,说明 Windows 下的图形后端与 QEMU 的视频设备存在兼容性问题。使用 VNC 可以将显示输出通过网络协议传输,完全绕过本地显卡驱动问题。
‌修改步骤:‌
‌移除‌ -device virtio-gpu-pci 和 -display gtk,gl=off。
‌添加‌ -vnc :0。
‌下载‌ VNC Viewer(如 TightVNC 或 RealVNC)。
‌连接‌ localhost:5900。
‌完整修正命令(VNC 模式):

REM---------------------------------------------------------------------------------------------------------安装----------------------------------------------------------------------------------------------
@echo off
setlocal enabledelayedexpansion

REM ==========================================
REM 配置区域 (请根据实际情况修改路径)
REM ==========================================
set ISO_FILE=ubuntu-22.04.5-live-server-arm64.iso
set DISK_FILE=ubuntu-arm64.qcow2
set BIOS_FILE=QEMU_EFI.fd
set QEMU_BIN=qemu-system-aarch64


echo ==========================================
echo QEMU ARM64 Ubuntu 安装助手
echo ==========================================
echo.

REM 1. 检查 QEMU 是否已安装并在 PATH 中
where %QEMU_BIN% >nul 2>nul
if %ERRORLEVEL% neq 0 (
echo [错误] 未找到 qemu-system-aarch64
echo 请确认已安装 QEMU 并将其安装目录添加到系统环境变量 PATH 中。
echo 推荐下载地址: https://qemu.weilnetz.de/w64/
pause
exit /b 1
)

REM 2. 检查 ISO 文件是否存在
if not exist "%ISO_FILE%" (
echo [错误] 找不到 ISO 文件: %ISO_FILE%
echo 请下载 Ubuntu Server ARM64 ISO 并放置在此脚本同一目录下。
pause
exit /b 1
)

REM 3. 检查 BIOS/UEFI 固件文件是否存在
if not exist "%BIOS_FILE%" (
echo [错误] 找不到 BIOS 文件: %BIOS_FILE%
echo 请下载 QEMU_EFI.fd Linaro UEFI 并放置在此11脚本同一目录下。
pause
exit /b 1
)
REM 4. 检查并创建虚拟磁盘
if not exist "%DISK_FILE%" (
echo [信息] 检测到虚拟磁盘不存在,正在创建 %DISK_FILE% 60GB...
qemu-img create -f qcow2 "%DISK_FILE%" 60G
if %ERRORLEVEL% neq 0 (
echo [错误] 创建磁盘失败,请检查权限或磁盘空间。
pause
exit /b 1
)
echo [成功] 虚拟磁盘创建完成。
) else (
echo [信息] 发现现有虚拟磁盘: %DISK_FILE%
)
echo.
echo [提示] 即将启动虚拟机...
echo 1. 首次启动可能较慢,请耐心等待 UEFI 自检和内核加载。
echo 2. 如果窗口黑屏,请点击窗口内部并按几次回车键。
echo 3. 按 Ctrl+Alt+G 可释放鼠标焦点。
echo.
pause

REM ==========================================
REM 启动命令
REM 关键修改:
REM 1. 移除 ,gl=on 以避免 Windows 显卡驱动兼容性问题导致的黑屏/无响应
REM 2. 使用 -display sdl 作为最通用的图形后端
REM 3. 确保每行末尾的^ 后没有任何空格
REM ==========================================
%QEMU_BIN% ^
-M virt ^
-cpu cortex-a72 ^
-m 8G ^
-smp 4 ^
-bios %BIOS_FILE% ^
-device virtio-gpu ^
-display gtk,gl=off ^
-device nec-usb-xhci,id=xhci ^
-device usb-kbd,bus=xhci.0 ^
-device usb-mouse,bus=xhci.0 ^
-device virtio-net-device,netdev=net0 ^
-netdev user,id=net0,hostfwd=tcp::2223-:22 ^
-drive file=%DISK_FILE%,if=none,id=hd0,format=qcow2 ^
-device virtio-blk-device,drive=hd0 ^
-cdrom %ISO_FILE% ^
-name "Ubuntu-22.04-ARM64-Installer"


echo.
echo [信息] QEMU 进程已退出。
pause
endlocal
REM---------------------------------------------------------------------------------------------------------安装End-------------------------------------------------------------------------------------------

REM---------------------------------------------------------------------------------------------------------启动----------------------------------------------------------------------------------------------
@echo off
setlocal enabledelayedexpansion

REM ==========================================
REM 配置区域 (请根据实际情况修改路径)
REM ==========================================
set ISO_FILE=ubuntu-22.04.5-live-server-arm64.iso
set DISK_FILE=ubuntu-arm64.qcow2
set BIOS_FILE=QEMU_EFI.fd
set QEMU_BIN=qemu-system-aarch64

echo.
echo [提示] 即将启动虚拟机...
echo 1. 首次启动可能较慢,请耐心等待 UEFI 自检和内核加载。
echo 2. 如果窗口黑屏,请点击窗口内部并按几次回车键。
echo 3. 按 Ctrl+Alt+G 可释放鼠标焦点。
echo.

REM ==========================================
REM 启动命令
REM 关键修改:
REM 1. 移除 ,gl=on 以避免 Windows 显卡驱动兼容性问题导致的黑屏/无响应
REM 2. 使用 -display sdl 作为最通用的图形后端
REM 3. 确保每行末尾的^ 后没有任何空格
REM ==========================================
%QEMU_BIN% ^
-M virt ^
-cpu cortex-a72 ^
-m 8G ^
-smp 4 ^
-bios %BIOS_FILE% ^
-device virtio-gpu ^
-display gtk,gl=off ^
-device nec-usb-xhci,id=xhci ^
-device usb-kbd,bus=xhci.0 ^
-device usb-mouse,bus=xhci.0 ^
-device virtio-net-device,netdev=net0 ^
-netdev user,id=net0,hostfwd=tcp::2223-:22 ^
-drive file=%DISK_FILE%,if=none,id=hd0,format=qcow2 ^
-device virtio-blk-device,drive=hd0 ^
-name "Ubuntu-22.04-ARM64-Installer"


echo.
echo [信息] QEMU 进程已退出。
pause
endlocal
REM---------------------------------------------------------------------------------------------------------启动End----------------------------------------------------------------------------------------------