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 beforeretit points back to the oldbpvalue.retwill 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 bycallinstructions, which does the counter-action ofret, push address of next instruction aftercallon stack, and then setsipto the argument value fromcallinstruction).But in your code the
ipis set to oldbpvalue, 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 bpahead ofret(after restoringspvalue bymov sp,bp).Whenever you manipulate stack, either explicitly by
push/poporadd/sub sp, or implicitly bycall/ret, make sure you end with correctspvalue in every code path before using stack further. Ie. usually everypushneeds it's pairingpopand everycallshould 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, 4ChOS service call.