Retrieving paras from the stack in 16-bit code

Started by jj2007, December 18, 2011, 10:27:36 PM

Previous topic - Next topic

jj2007

I've tried mov di, [sp+4] but my assemblers don't like it ::)
The two snippets below both work. Question: Is mov ax, [esp+8] a safe way to retrieve a para from stack?

if 0
push bp
mov bp, sp
mov di, [bp+8] ; arg1
mov bx, [bp+10] ; arg2
pop bp
else
mov di, [esp+8] ; arg1
mov bx, [esp+10] ; arg2
endif

qWord

hi,
16Bit addressing has not the same capacities as 32Bit. You will find a table off all possible combinations in Intel's  instruction set reference (chapter 2.1.5)
FPU in a trice: SmplMath
It's that simple!

sinsi

There is no opcode for [sp], I guess that's why they made bp.
The only problem I can see is if the high word of esp is not 0, then you will get a GP exception, since the SS register will have a 64K limit.
Light travels faster than sound, that's why some people seem bright until you hear them.

jj2007

Thanks a lot.
> if the high word of esp is not 0
Sinsi, is that a practical or hypothetical case?
Do I get bp back intact after an interrupt?

sinsi

Normal 16-bit real mode segment registers have a limit of 64K so if the calculated offset is bigger you get a GP fault.
I haven't used ESP before but have used things like [EAX+EDX*4] in DOS code with no dramas.

After an interrupt you should get all registers back intact, as long as the ISR saves and restores them (which it should).
Light travels faster than sound, that's why some people seem bright until you hear them.

mineiro

.com programs have a maximum size of 64k, because it fits in only one segment.(xxxx:ffffh). In default, near call's are made.
Interruptions that I have see preserve all registers, but some of then destroy flags.
You need take care if the procedure that receive parameters is valid to a far call or near call.

.model small
.386
.stack 100
.code
start:
push ss  ;just for fun
pop ds   ;idem
mov eax,1
mov ebx,2
push ax
push bx
push sp ;for fun
pop si    ;idem
call cs:test1 ;push cs => far call
call tes ;near call
pop bx
pop ax
ali:
        ; exit to DOS
        mov     ax, 4C00h
        int     21h
tes proc            
push bp          
mov bp,sp        
mov ax,ds:[bp+6] 
mov ax,ds:[si+2] 
mov bx,ss:[bp+4]   
pop bp            
ret            
tes endp                       

test1 proc
push bp
mov bp,sp
mov ax,[bp+8]
mov bx,[bp+6]
pop bp
retf    ;ret 2
test1 endp
end start

dedndave

the max size for a .com program is 64 kb - 256 bytes for the PSP
you can load more stuff afterwards, but the loader will not handle .COM files larger than 65280 bytes

when an INT occurs, whether hardware or software generated, the flags are pushed onto the stack
then the CS, then the RET IP address
generally, INT's that alter the flags only affect the carry flag to indicate success or failure
they do this by setting or clearing the appropriate bit in the saved flags on the stack
of course, an INT handler can be written to do otherwise   :P

mineiro

very well remembered Sr dedndave, thats why we need do an "org 100h" in .com programs.

About intersegment calls, I have done this simple example:
.model HUGE
.386
.stack 100
.code main
start:
call seg_2:te
        mov     ax, 4C00h
        int     21h

.code seg_2
te proc
retf
te endp
end start

jj2007