ARM 汇编指令:PUSH 和 POP

ARM 汇编指令:PUSH 和 POP

本文来自于我关于 ARM 汇编指令系列文章。欢迎阅读、点评与交流~
1、汇编指令在不同架构中的联系与区别
2、ARM 汇编指令:MOV
3、ARM 汇编指令:LDR
4、ARM 汇编指令:STR
5、ARM 汇编指令:MRS 和 MSR
6、ARM 汇编指令:ORRS
7、ARM 汇编指令:BEQ
8、ARM 汇编指令:TST
9、ARM 汇编指令:B
10、ARM 汇编指令:BX
11、ARM 汇编指令:ERET

在 ARM 汇编中,PUSHPOP 是用于栈操作(堆栈操作)的指令,主要用于保存和恢复寄存器的值。它们是 STMDBLDMIA 的别名,与栈指针(通常是 SP)一起使用。


1. 栈的概念

  • ARM 中栈通常是 满递减栈(Full Descending, FD),即栈向低地址方向生长,栈指针指向最后一个入栈的元素。
  • PUSH 用于将寄存器值存入栈(压栈)。
  • POP 用于从栈中取出值到寄存器(出栈)。

2. PUSH 指令

语法

assembly 复制代码
PUSH {reg_list}

功能

  • reg_list 中的寄存器依次存入栈(从高寄存器到低寄存器顺序存入内存,但内存地址递减)。

  • SP 会先递减(因为是满栈),然后再存数据。

  • 等价于:

    assembly 复制代码
    STMDB SP!, {reg_list}

    STMDB 表示先递减(Decrease Before)存储。

示例

assembly 复制代码
PUSH {R0, R1, R4-R7}   ; 将 R0, R1, R4, R5, R6, R7 压栈

假设入栈前 SP = 0x1000,入栈 6 个寄存器(每个 4 字节)后 SP = 0x1000 - 0x18 = 0xFE8


3. POP 指令

语法

assembly 复制代码
POP {reg_list}

功能

  • 从栈中取出数据到 reg_list 中的寄存器(从低地址到高地址加载到寄存器,寄存器的编号顺序不影响加载的内存顺序,但通常按编号升序弹出到寄存器列表中的寄存器)。

  • SP 会在加载后递增(因为是满栈)。

  • 等价于:

    assembly 复制代码
    LDMIA SP!, {reg_list}

    LDMIA 表示先递增(Increase After)加载。

示例

assembly 复制代码
POP {R0, R1, R4-R7}   ; 恢复 R0, R1, R4, R5, R6, R7 的值

4. 使用场景

子程序调用时保存现场:

assembly 复制代码
subroutine:
    PUSH {R0-R3, LR}   ; 保存工作寄存器和返回地址
    ...                ; 子程序代码
    POP {R0-R3, PC}    ; 恢复寄存器并返回(将 LR 弹出到 PC)

注意:这里 POP {..., PC} 相当于同时恢复了寄存器并跳转回调用处。


5. 注意事项

  • 寄存器顺序 :在 PUSHPOP 的寄存器列表中,可以按任意顺序书写,但汇编器会按寄存器编号升序排序后再压栈(编号高的寄存器对应高内存地址)。出栈时,低内存地址的数据弹出到列表中编号最小的寄存器。
  • 栈对齐 :在 ARMv7/AArch32 中,通常要求 SP 对齐到 8 字节(特别是在调用公共接口时)。在 AArch64 中,PUSH/POP 指令形式不同,并且要求 16 字节对齐。
  • Thumb 模式 :在 Thumb 指令集中,PUSH/POP 的寄存器列表有限制(通常只能用于通用寄存器和 LR/PC)。

6. 示例:完整的函数调用与返回

assembly 复制代码
main:
    ...
    BL foo
    ...

foo:
    PUSH {R4-R7, LR}      ; 保存调用者保存的寄存器和返回地址
    ...                   ; 使用这些寄存器
    POP {R4-R7, PC}       ; 恢复寄存器并直接返回

7. 与 x86 的区别

  • x86 的 PUSH/POP 一次只能操作一个寄存器或内存地址,而 ARM 可以一次操作多个寄存器。
  • ARM 的栈操作更加灵活,可以通过 STM/LDM 实现多种栈模式(但 PUSH/POP 固定为满递减)。
相关推荐
sunoo-2293 小时前
【嵌入式裸机开发Day04】i.MX6ULL 蜂鸣器驱动详解:从引脚地址查找到代码实现全流程
arm开发·单片机·嵌入式硬件·学习·串口·裸机
Doraemomo4 小时前
IMX6ULL裸机开发——PWM
arm开发·嵌入式硬件·imx6ull
老当益壮梁奶奶5 小时前
ARM汇编学习笔记(五):从按键轮询到 GIC 中断控制器(ARM Cortex-A7 )
arm开发·笔记·单片机·嵌入式硬件
M78佐菲6 小时前
ARM学习笔记(五)
linux·arm开发·笔记·嵌入式硬件·学习
小诗懂技术8 小时前
ARM 裸机中断:从按键到 GIC 的处理流程
arm开发
从零开始的嵌入式之旅8 小时前
day46
linux·arm开发·笔记·嵌入式硬件
老当益壮梁奶奶8 小时前
ARM汇编学习笔记(四):i.MX6ULL裸机开发:从汇编点灯到C语言BSP工程管理
c语言·arm开发·单片机·嵌入式硬件·51单片机
sunoo-2298 小时前
【ARM嵌入式学习笔记Day5】一文打通GPIO中断全链路:从硬件引脚→GIC→汇编入口→C语言处理
arm开发·笔记·学习·中断·gic·裸机开发
PiaoKe___12 小时前
云手机原理与 Python 自动化实战:ADB 批量控制、任务调度与落地建议
服务器·arm开发·python·自动化
斑马1391 天前
ARM学习笔记(二)——ARM汇编基础
汇编·arm开发·arm