ARM mips架构学习

ARM

汇编相关

寄存器相关

寄存器名称 别名 作用
r0 通用寄存器
r1
r2
r3
r4
r5
r6
r7 存系统调用号
r8 通用寄存器
r9
r10
r11 FP 帧指针,类似EBP
r12 IP 程序内调用
r13 SP 栈指针
r14 LR 链接寄存器
r15 PC 程序计数器,类似EIP
CPSR 当前程序状态寄存器

函数调用时参数

规定前4个参数,由寄存器 r0123 传,后几个参数放栈上

启动及调试

启动

32位

1
2
3
qemu-arm -L /usr/arm-linux-gnueabihf ./your_program # 动态链接
# 若有给依赖,则将-L后的路径改为依赖的路径即可
qemu-arm ./your_program # 静态

64位

1
2
3
qemu-aarch64 -L /usr/aarch64-linux-gnu ./your_program # 动态链接
# 若有给依赖,则将-L后的路径改为依赖的路径即可
qemu-aarch64 ./your_program # 静态

调试

启动时加上 -g 后加端口

比如

1
qemu-arm -g 1234 -L /usr/arm-linux-gnueabihf ./your_program

然后启动 gdb

1
2
3
gdb-multiarch
# 进入gdb
target remote localhost:上文的端口号

然后就可以调试了

mips

寄存器

寄存器 别名 用途
$0 $zero 常量0
$1 $at 保留给汇编器,用于临时计算,程序员不应直接使用
$2-$3 $v0-$v1 存储函数返回值
$4-$7 $a0-$a3 函数调用参数,其他存栈上
$8-$15 $t0-$t6 临时寄存器用于函数内部计算,不需要保存
$16-$23 $s0-$s7 保存寄存器。保存函数调用期间的值
$24-$25 $t8-$t9 临时寄存器,通常不需要在函数调用中保存
$26-$27 $k0-$k1 保留给操作系统内核,通常用于内核中系统调用或中断处理
$28 $gp 全局指针,指向全局数据区域基地址,便于访问全局变量
$29 $sp 堆栈指针,指向当前堆栈顶部
$30 $fp 帧指针,指向当前栈帧基地址
$31 $ra 返回地址
PC PC 保存正在执行指令地址,并在指令执行后自动递增指向下一条指令

重要的

  • $ra ,保存了返回地址,也是我们溢出的目标
  • 函数调用参数:$a0-$a3

特点

  1. mips所有指令都是4字节长
  2. 无NX,其栈/bss段通常都是可执行的
  3. 延迟槽
    • mips流水线设计的一个历史遗留特性,任何跳转或分支指令(如j jalr jr)的后面紧跟的那一条指令,总会被优先与这个跳转指向
    • 比如
1
2
jalr aabb
mov $a0,$s0 # 这一条会在跳转前执行
  1. 跳转一致性问题
    • mips cpu通常由独立的指令缓存( I-Cache )和数据缓存(D-Cache)
    • 当我们栈溢出将 shellcode 写入栈上,我们修改的是数据缓存,cpu 执行时,是从指令缓存中读取,此时 I-Cache 中可能是旧的数据,导致执行失败
    • 解决:在跳转到 shellcode 前,手动调用 cacheflush 系统调用,强行清空指令缓存,让 cpu 从内存中重新加载我们的 shellcode

指令格式

  • R格式

op rs rt rd shamt funct

用于寄存器间操作(如算数,逻辑),例如ad

  • I格式

op rs rt 立即数操作

用于立即数操作,加载,存储,分支等,如lw

  • J格式

op t跳转地址

用于跳转

常见指令

  • add

add $rd,$rs,$rt rd=rs+rt

  • lw

加载字(32位)

lw $rt,offset($rs) 从地址rs+offset加载4字节到rt

  • sw

lw $rt,offset($rs) 从地址rt加载4字节到rs+offset加载4字节到

  • lb sb 8字节

  • j 无条件跳转

j target

  • jal

jal target 跳转到 target 并将返回地址存在 ra 中

  • jr 寄存器跳转

jal $rs 跳转到 rs 存的地址中

  • nop

空,常用于填充延迟槽


ARM mips架构学习
http://yyyffff.github.io/2025/09/18/ARM mips架构学习/
作者
yyyffff
发布于
2025年9月18日
许可协议