[英]Instruction sequence that does the same thing as push
我想知道是否有可能(如果可以,如何)編寫一系列與push
具有相同效果的指令。 例如,如果ax
的內容為1200,而我執行了a push ax
,那么我還可以使用其他哪些指令來完成a push ax
呢?
其他一些答案使用[sp]
進行堆棧尋址,但是在16位模式或32位或64位模式下都不可能。 但是,在32位模式下,可以使用[esp]
;在x86-64中,可以將[rsp]
用於內存尋址,但是在16位模式下,沒有使用sp
內存尋址。 有關16位模式下可能的存儲器尋址模式,請參見此處 。
因此,您需要做的是:將bp
的值存儲在某個地方,將sp
復制到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
這樣的內存地址也很簡單。
編輯:添加了不修改標志的版本(如下所示),因為push
也不修改標志。
上面的代碼修改了標志,而push ax
並沒有修改任何標志。 這可以通過存儲第一要解決ah
到存儲器中,然后加載標志成ah
與lahf
,然后從存儲的標志ah
到存儲器,那么修改所述堆如上述,然后之后從存儲器經由恢復標志ah
通過使用sahf
最后恢復從內存ah
。
編輯:要模擬沒有更改標志的push ax
,必須在lahf
之前保存lahf
並在mov [bp],ax
之前加載ah
。 固定。
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
修改AF
, CF
, OF
, PF
, SF
, ZF
,而lahf
加載和sahf
僅存儲AF
, CF
, PF
, SF
, ZF
(無OF
)。 但是, sp
絕不會在正常堆棧使用中溢出。
但是,如果您無法訪問內存,並且希望使用堆棧來存儲bp
,則可以執行此操作,但是如果您都沒有可用的免費寄存器,那么事情將會變得復雜。 但是,如果您使用的是實模式操作系統,則可以使用cli
阻止中斷,交換bp
和sp
,使用bp
進行堆棧尋址,再次交換bp
和sp
,並再次使用sti
允許中斷。
編輯: sp
的值需要減去2以模擬push ax
。 固定。 此版本不修改標志(中斷標志除外)。
cli
xchg bp,sp
lea bp,[bp-2]
mov [bp],ax
xchg bp,sp
sti
至少如果有內存,它大致相當於:
sub sp, 2
mov [sp], ax
減去一個等於sp所需數據寫入大小的值,然后在堆棧上移動/寫入所需的對象。 編譯器一直在做這種事情。 查看-S輸出示例。 如果執行此操作,請當心原子/線程問題...
如果我沒有忘記英特爾語法:
lea sp, [sp-2]
mov [sp], ax
我用lea
避免接觸FLAGS
(既不push
也不是mov
或lea
觸摸它們,但sub
和dec
做)。
編輯:原來,我已經忘記了更重要的事情:沒有[sp]
尋址模式。 正確答案是@nrz給出的答案,我的答案可以應用於80386及更高版本上的esp
和eax
(將為lea esp,[esp-4]
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.