是否可以将寄存器与堆栈顶部的项目进行比较,而无需先弹出它?
EG这种方式我可以做到,但我必须先弹出值:
push 1
pop ax
cmp ax,1
jz equal
是否可以在不修改堆栈的情况下做到这一点?
如果您专门谈论 8086(而不是 x86 系列),那么不,我不相信存在使用堆栈指针的非直接寄存器模式。
基本选项是:
[BX] [SI]
<displacement> or or
[BP] [DI]
当然,如果您没有将它用于其他任何事情,您可以将堆栈指针转移到,然后使用它:BP
mov bp, sp
mov ax, [bp]
; now check ax
或者,如果您不介意在很短的时间内更改堆栈(但请注意中断是否会导致您出现问题,它们可能会在pop
and之间触发push
):
pop ax
push ax
; now check ax
在任何 asm exe 的最开始,您声明一个内存块来记录堆栈的顶部
STAK dw[0]
并使用 bx 存储栈顶 sp
mov bx,STAK
mov [bx],sp
然后在需要比较时使用 bx 与任意寄存器进行比较,bx 是一个指向寄存器
mov bx,[STAK]
cmp ax,[bx]
如果需要,您可以使用 bp 而不是 bx
如果在 32 位保护模式下使用 x86 系列处理器(80386 及更高版本),则在不使用 PUSH 或 POP 的情况下将堆栈顶部与 AX 进行比较非常容易,因为所有通用寄存器都可以用作基本索引。
CMP AX, [ESP] ; compare top of stack with AX
CMP EAX, [ESP] ; compare top of stack with EAX
从 IA32 指令集参考手册的“表 2-1. 带有 ModR/M 字节的 16 位寻址形式”中,可以使用以下组合。
[BX] + displacment
[BP] + displacement
[SI] + displacement
[DI] + displacement
[BX + SI] + displacement
[BX + DI] + displacement
[BP + SI] + displacement
[BP + DI] + displacement
不幸的是,在 16 位模式下使用堆栈寄存器不是其中之一(例如在 8086 上)。这意味着要在不使用 PUSH 或 POP 的情况下访问栈顶,您必须首先将 SP 寄存器的内容移动到 BX、BP、SI 或 DI,然后使用其中一个寄存器来访问栈顶元素.
您必须注意几个问题。您必须确保寄存器的默认段寄存器与堆栈段寄存器 SS 匹配,或者必须显式强制使用特定的段寄存器和寄存器。自从我完成任何 16 位编码以来已经有很长一段时间了,所以现在有些规则让我无法理解。手册肯定会包含它们。
BP 寄存器默认使用堆栈段 SS。它还用于在例程内创建堆栈帧,并用于索引以获取在堆栈上传递的参数以及本地堆栈变量。
PUSH BP ; These two lines are often used to create the stack
MOV BP, SP ; at the start of a routine
SUB SP, # ; Carve space on the stack for local stack variables
一个典型的堆栈框架可能看起来像......
[BP + 6] ; 16-bit parameter
[BP + 4] ; 16-bit parameter
[BP + 2] ; return address IP saved on stack
[BP + 0] ; saved BP on stack
[BP - 2] ; 16-bit local variable on the stack
[BP - 4] ; 16-bit local variable on the stack
希望这可以帮助。