Some other answers use [sp]
to address the stack, but this is not possible in 16-bit mode, as well as in 32-bit or 64-bit modes. However, in 32-bit mode you can use [esp]
, and in x86-64 you can use [rsp]
to address memory, but in 16-bit mode address memory is not used sp
. See here for possible memory addressing modes in 16-bit mode.
So what you need to do: save the bp
value somewhere, copy sp
to bp
, then use bp
to address the stack and finally restore the original bp
value.
If you have bp
storage space, this is easy (this is in the 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 a memory address such as bp_storage
is also trivial here.
Edit: A version has been added that does not change flags (below), since push
also does not change flags.
The code above changes flags, while push ax
does not change any flags. This can be solved by storing the first ah
in memory, and then loading the flags in ah
using lahf
, then storing the flags from ah
into memory, then changing the stack as described above, and then restoring the flags from memory through ah
using sahf
and finally , recover ah
from memory.
Edit: To simulate push ax
without changing flags, ah
must be saved to lahf
and loaded to 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
, and lahf
loads and sahf
stores only AF
, CF
, PF
, SF
, ZF
(no OF
). However, sp
should never overflow with normal stack usage.
But if you cannot access memory and want to use the stack to store bp
, you can do it, but if you don't have free registers, things get more complicated. But if you use a real mode OS, you can block interrupts with cli
, exchange bp
and sp
, use bp
to address the stack, exchange bp
and sp
again and enable interrupts again with sti
.
Edit: The sp
value must be subtracted by 2 to simulate push ax
. Fixed. This version does not change flags (except interrupt flag).
cli xchg bp,sp lea bp,[bp-2] mov [bp],ax xchg bp,sp sti