其他一些答案使用[sp]
用于堆栈寻址,但在 16 位模式下不可能,在 32 位或 64 位模式下也不可能。但是,在 32 位模式下您可以使用[esp]
在 x86-64 中你可以使用[rsp]
用于内存寻址,但在 16 位模式下,没有使用的内存寻址sp
. See here http://sandpile.org/x86/opc_rm16.htm了解 16 位模式下可能的存储器寻址模式。
所以,你需要做的是:存储bp
某处,复制sp
into bp
,然后使用bp
进行栈寻址,最后恢复原来的值bp
.
如果你有地方可以存放bp
,这很简单(这是 YASM/NASM 语法):
mov [bp_storage], bp
sub sp,2
mov bp,sp
mov [bp],ax
mov bp,[bp_storage]
...
bp_storage dw 0
使用寄存器代替内存地址,例如bp_storage
这也是微不足道的。
Edit:添加了不修改标志的版本(如下),如下push
也不修改标志。
上面的代码修改了标志,而push ax
不修改任何标志。可以通过先存储来解决ah
到内存中,然后将标志加载到ah
with lahf
,然后存储来自ah
到内存,然后如上所述修改堆栈,然后通过以下方式从内存恢复标志ah
通过使用sahf
并最终恢复ah
从记忆里。
Edit:模拟push ax
不改变标志,ah
之前必须保存lahf
并在之前加载mov [bp],ax
. Fixed.
mov [ah_storage],ah
lahf
mov [flags_storage],ah
mov [bp_storage],bp
sub sp,2
mov bp,sp
mov ah,[ah_storage]
mov [bp],ax
mov bp,[bp_storage]
mov ah,[flags_storage]
sahf
mov ah,[ah_storage]
...
bp_storage dw 0
ah_storage db 0
flags_storage db 0
sub http://web.itu.edu.tr/kesgin/mul06/intel/instr/sub.html修改AF
, CF
, OF
, PF
, SF
, ZF
, 然而lahf http://web.itu.edu.tr/kesgin/mul06/intel/instr/lahf.html负载和sahf http://web.itu.edu.tr/kesgin/mul06/intel/instr/sahf.html仅限商店AF
, CF
, PF
, SF
, ZF
(no OF
)。然而,sp
在正常的堆栈使用中永远不应该溢出。
但是,如果你无法访问内存,并且想使用堆栈来存储bp
你可以这样做,但如果你没有可用的免费寄存器,事情就会变得复杂。但如果您使用的是实模式操作系统,则可以使用以下命令阻止中断cli
, 交换bp
and sp
, use bp
用于堆栈寻址、交换bp
and sp
再次并允许再次中断sti
.
Edit:的价值sp
需要减去2来模拟push ax
。固定的。该版本不修改标志(中断标志除外)。
cli
xchg bp,sp
lea bp,[bp-2]
mov [bp],ax
xchg bp,sp
sti