原文请参照Intel开发者手册: Intel® 64 and IA-32 Architectures Software Developer’s Manual
pusha/pushad——push all the general-purpose registers
Opcode | Instruction | Op/En | 64-bit Mode | Compat/Leg Mode | Description |
---|---|---|---|---|---|
60 | pusha | np | invalid | valid | Push AX, CX, DX, BX, original SP, BP, SI, and DI. |
60 | pushad | np | invalid | valid | Push EAX, ECX, EDX, EBX, original ESP, EBP, ESI, and EDI. |
Op/En | Operand1 | Operand2 | Operand3 | Operand4 |
---|---|---|---|---|
NP | NA | NA | NA | NA |
pusha/pushad描述
pusha/pushad将通用寄存器的数据压栈,寄存器的数据以AX, CX, DX, BX, original SP, BP, SI, and DI.(EAX, ECX, EDX, EBX, original ESP, EBP, ESI, and EDI.)的顺序进栈,popa和popad可以执行与之相反的操作。pusha/pushad和popa/popad都不影响标志位寄存器。
pusha(push all)与pushad(push all double)指令有相同的opcode,pusha/pushad用在操作数为16/32位的程序。使用pusha/pushad时有些汇编器会强制把操作数变为16/32位,有些编译器把pusha和pushad同样对待,操作数大小决定了进栈值的宽度。
在实地址模式(real-address mode),当pusha或pushad执行时,如果esp或sp寄存器的值为1,3或5,会产生一个非传递的异常#SS(栈错误报告阻止了#SS传递)。接着,处理器产生一个异常#DF并进入停机状态(停机状态的具体描述请参考 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A.)
如第一个表格,pusha/pushad可以在兼容模式(compatibility mode)和遗留模式(legacy mode)执行,但是在64位模式(64-bit mode)中是无效的
pusha/pushad的具体操作
if 64-bit mode
then #UD
fi;
if OperandSize == 32
then
mov temp esp
push eax
push ecx
push edx
push ebx
push temp
push ebp
push esi
push edi
else
mov temp sp
push ax
push cx
push dx
push bx
push temp
push bp
push si
push di
fi;
pusha/pushad使用时可能发生的异常
保护模式异常
- #SS(0)
开始和结束的栈地址超过了栈段的边缘会引发改异常 - #PF(fault-code)
页错误发生会引发该异常 - #AC(0)
目前特权等级是3且开启对齐检测,如果非对齐内存被使用会引发该异常 - UD
LOCK前缀被使用会引发该异常
实地址模式异常
- #GP
ESP或SP寄存器是 7, 9, 11, 13, or 15时触发该异常 - #UD
LOCK前缀被使用时触发该异常
虚拟8086模式异常
- #GP(0)
ESP或SP寄存器是 7, 9, 11, 13, or 15时触发该异常 - #PF(fault-code)
页错误发生会引发该异常 - #AC(0)
开启对齐检测,如果非对齐内存被使用会引发该异常 - #UD
LOCK前缀被使用时触发该异常
兼容模式异常
和保护模式的异常一致
64位模式异常
- #UD
在64位中使用pusha/pushad触发该异常