When I run my program the assembler says:
PROGRAM HAS RETURNED CONTROL TO THE OPERATING SYSTEM
when it reaches the RET instruction. The code looks like:
twoMash PROC
push bp
mov bp, sp
sub sp, 2
NOT ax
ADD ax,1
mov sp,bp
ret
twoMash ENDP
main
is defined this way:
main:
mov ax,100b
push ax
call twoMash
The first instruction is
push bp
, so value on top of stack is now value frombp
.Then you do some more things, including manipulation of
sp
(pointer to top of stack), but just beforeret
it points back to the oldbp
value.ret
will pop value from stack, and setip
(instruction pointer) to that value. Under normal circumstances it is expected to have on top of stack the address of next instruction to execute (put there usually bycall
instructions, which does the counter-action ofret
, push address of next instruction aftercall
on stack, and then setsip
to the argument value fromcall
instruction).But in your code the
ip
is set to oldbp
value, which very likely points somewhere into stack memory (or "worse"), so the CPU will next try to execute data bytes as code, and the behaviour is unexpected (return to OS would be actually quite nice end result, such mistakes usually end in crash of application, or even loss of data).To fix, add
pop bp
ahead ofret
(after restoringsp
value bymov sp,bp
).Whenever you manipulate stack, either explicitly by
push/pop
oradd/sub sp
, or implicitly bycall/ret
, make sure you end with correctsp
value in every code path before using stack further. Ie. usually everypush
needs it's pairingpop
and everycall
should return byret
, unless you are experienced enough to break such rules and adjust stack to correct state by different means.BTW, it is questionable, whether there actually is return address at the stack at your entry point (it's not clear from your question, if you have some other code
call
-ing this, or it is entry point of your program).If this is like DOS executable, and it was entry point, then you should end your program with
int 21h, 4Ch
OS service call.