前言:
此刻同学们对“使用堆栈操作指令时要注意什么问题”大体比较着重,姐妹们都需要了解一些“使用堆栈操作指令时要注意什么问题”的相关资讯。那么小编也在网上网罗了一些对于“使用堆栈操作指令时要注意什么问题””的相关知识,希望姐妹们能喜欢,你们快快来学习一下吧!堆栈的概念
堆栈是在内存RAM中开辟的一段空间,利用“先进后出”或“后进先出”原则存取数据。
如果把数据压入堆栈,则堆栈指针的值是减少的,即所谓的向下生成堆栈。
由SS:SP(16位)或SS:ESP(32位)指向栈底(栈空)或栈顶(栈不空)地址。
利用数据入栈指令PUSH和数据出栈指令POP操作堆栈。
1.数据入栈指令
指令格式:PUSH OPS
功能:将OPS中的数据压入堆栈中。若压入堆栈中的OPS是16位,则SP(16位CPU)或ESP(32位CPU)减2;若OPS是32位,ESP(32位CPU)减4。
PUSH一般有如下三种:
PUSH reg16/32; 寄存器reg必须是16或32位PUSH segPUSH mem16/32; 内存中的数据必须是16或32位PUSH imm16/32; 将16位或32位立即数压入堆栈2.数据出栈指令
指令格式:POP OPD
功能:将栈顶元素弹出送到某一寄存器、段寄存器(CS除外)或内存中。注意OPS一定是16或32位。弹出栈的数据若是16位,SP或ESP加2;若数据是32位,ESP加4。
POP一般有如下三种:
POP reg16/32 ; 寄存器reg必须是16或32位POP seg ; seg不能为CS、SSPOP mem 16/32 ; 存储器长度必须是16或32位
弹出肯定是从栈顶开始:LIFO原先的ax在下面,要等到原先的Bx弹出再弹出ax。
AX,BX入栈后原来的数据还在;只不过经过出栈后原来的数据被修改了,结果是交换了数据。
栈实际上是个中转站。
数据的交换必须要通过第三方中转。
MOV CX,AXMOV DX,BXMOV AX,DXMOV BX,CX
这段指令实际上是利用CX,DX做中转站交换AX,BX;道理是一样的;
只不过栈的操作原则是LIFO。
PUSH/POP相关的其他指令
(1)存储器操作数入栈与出栈
PUSHW mem ; 16位存储器操作数入栈 PUSHD mem ; 32位存储器操作数入栈
或
PUSH WORD PTR mem(16) PUSH DWORD PTR mem(32) POP WORD PTR mem(16) POP DWORD PTR mem (32)
(2)多个16位通用寄存器入栈和出栈
16位数据入栈/出栈配对使用指令:PUSHA/POPA。
PUSHA:
将AX、BX、CX、DX、SP、BP、SI、DI这8个16位通用寄存器的值依次压入堆栈(指针减),其中SP的值是在此条指令未执行之前的值,该指令执行后,SP-16(字节)→SP。
POPA:
依次弹出堆栈中的16位字节到DI、SI、BP、SP、DX、CX、BX、AX中,该指令执行后,SP+16→SP。
(3)多个32位通用寄存器入栈与出栈
PUSHAD
将EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI这8个32位通用寄存器的值依次压入堆栈,其中ESP的值是在此条指令未执行之前的值,指令执行后,ESP-32→ESP。
POPAD
依次弹出堆栈中的32位字到EDI、ESI、EBP、ESP、EBX、EDX、ECX、EAX中,弹出完成后,ESP+32→ESP。
上述两组指令用于过程设计时,PUSHA和PUSHAD在过程开始时暂存通用寄存器的当前值,POPA和POPAD在过程结束时恢复通用寄存器的值,必须配对使用。
(4)16位标志寄存器F的入栈和出栈。
PUSHF ; 将16位标志寄存器F的值入栈POPF ; 将栈顶弹出2个字节送给16位标志寄存器F,; 或弹出送到32位标志寄存器的低16位中。
操作码POPF的含义是:pop flags off stack。
(5)32位标志寄存器入栈和出栈
PUSHFD ; 是将32位标志寄存器EFLAGS的值; 入栈POPFD ; 从堆栈栈顶处连续弹出4字节送 ; 给32位的标志寄存器EFLAGS
当从堆栈中弹出4字节送给32位标志寄存器时,只有在当前特权级为0时,才能从堆栈中弹出4字节标志送给EFLAGS,使得EFLAGS中的I/O特权级标志位IOPL才能被替换。
(6)ENTER和LEAVE指令
ENTER/LEAVE指令把EBP寄存器内容入栈/出栈,并在堆栈中为局部变量分配/释放存储空间,通常在子程序调用时使用该组指令。