Instruction sequence that does the same thing as p

2019-06-24 08:43发布

I would like to know if it is possible (and if so, how) to write a sequence of instructions that would have the same effect as push. For example, if the contents of ax is 1200 , and I do a push ax, what other instructions can I use to accomplish what push ax does?

4条回答
smile是对你的礼貌
2楼-- · 2019-06-24 09:08

Some other answers use [sp] for stack addressing, but it is not possible in 16-bit mode, nor in 32-bit or 64-bit modes either. However, in 32-bit mode you can use [esp] and in x86-64 you can use [rsp] for memory addressing, but in 16-bit mode there is no memory addressing that uses sp. See here for possible memory addressing modes in 16-bit mode.

So, what you need to do: store the value of bp somewhere, copy sp into bp, then use bp for addressing the stack, and finally restore the original value of bp.

If you have a place where to store bp, that's easy (this is in YASM/NASM syntax):

mov [bp_storage], bp
sub sp,2
mov bp,sp
mov [bp],ax
mov bp,[bp_storage]

...

bp_storage dw 0

Using a register instead of memory address like bp_storage here is trivial too.

Edit: Added version that does not modify flags (below), as push doesn't modify flags either.

The code above modifies flags, whereas push ax does not modify any flags. That can be solved by storing first ah into memory, then loading flags into ah with lahf, then storing the flags from ah to memory, then modifying the stack as above, and then afterwards restoring flags from memory via ah by using sahf and finally restoring ah from memory.

Edit: To simulate push ax without changes in flags, ah must be saved before lahf and loaded before 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 modifies AF, CF, OF, PF, SF, ZF, whereas lahf loads and sahf stores only AF, CF, PF, SF, ZF (no OF). However, sp should never overflow in normal stack usage.

But, if you can't access memory, and want to use stack to store bp you can do that, but if you neither have free registers to use, things get complicated. But if you are using a real mode OS, you can block interrupts with cli, exchange bp and sp, use bp for stack addressing, exchange bp and sp again and allow interrupts again with sti.

Edit: the value of sp needs to subtracted by 2 to simulate push ax. Fixed. This version does not modify flags (except interrupt flag).

cli
xchg bp,sp
lea bp,[bp-2]
mov [bp],ax
xchg bp,sp
sti
查看更多
老娘就宠你
3楼-- · 2019-06-24 09:16

At least if memory serves, it's roughly equivalent to:

sub sp, 2
mov [sp], ax
查看更多
萌系小妹纸
4楼-- · 2019-06-24 09:17

Subtract a value that equals the size of the data write required from the sp, then move/write on the stack the objects you want. Compilers do this sort of thing all the time. Look at a -S output for examples. Beware of atomic/thread issues if you do this...

查看更多
够拽才男人
5楼-- · 2019-06-24 09:27

If I've not forgotten the Intel syntax:

lea sp, [sp-2]
mov [sp], ax

I've used lea to avoid touching FLAGS (neither push nor mov or lea touch them, but sub and dec do).

EDIT: It turns out that I've forgotten more important thing: there is no [sp] addressing mode. The correct answer is the one by @nrz, mine could be applied to esp and eax (would be lea esp,[esp-4]) on 80386 and above.

查看更多
登录 后发表回答