I'm learning how to pass parameters to a function via the stack. I find myself in a situation where I don't understand why (once I've done the various pop's on the stack to save the data), going backwards with the instruction (see DEBUG comments):
mov ax, [bp + n]
I end up with a 2-byte offset.
I'll explain.
I have sketched everything that happens exclusively on the stack. When I get to education:
mov bp, sp
I copy the address contained in sp in bp (which in my case is 00f8h). Well, it makes me think now that everything I refer to from now on, using [bp + n], starts from this address.
So, referring to the area that I commented as DEBUG, if bp = 00f8h and I want to view the content, I should find the byte that I left unchanged with the instruction sub sp, 2, instead I find myself the starting address that had bp (2 bytes higher than 00f8h).
Going on with the next DEBUG statement, I have:
mov ax, [bp + 2]
I should find the value I had memorized of bp; instead I find myself the return address of the call (4 bytes higher than 00f8h).
The program instruction:
mov ax, [bp + 4]
I should find the return address of the procedure call. Instead I find the value I had saved from the cx register.
In short, it seems that bp does not refer to 00f8h but rather to 00fah (2 bytes higher), so that the accounts add up (unfortunately, however, in the registers I see that this is not the case).
Please do not consider the form in which I try to handle the situation of passing parameters; my problem is:
why is there this 2-byte offset?
; Use parameterized procedures.
;
;
; To assemble an .ASM file with TASM:
; # TASM PUNTATOR.ASM /L /ZI
; # TLINK PUNTATOR.OBJ /V
dosseg
.model medium
.stack 100h
.data
num1 db 5
num2 db 3
ris db ?
.code
main proc
mov ax, dgroup ; mette il segmento dati in AX
mov ds, ax ; imposta DS in modo da puntare ai dati
xor cx, cx ; I clean up the cx registry
mov cl, num1 ; cx = 5
xor bx, bx ; I clean up the bx registry
mov bl, num2 ; bx = 3
push bx ; 2° parameter
push cx ; 1° parameter
xor ax, ax ; I prepare ax to hold the return parameter
call somma
add sp, 4 ; it's like I'm doing two pops. That is, I restore the
; stack pointer to its original value, before calling
; the two parameters above.
mov ris, al
mov ah, 02h
mov dl, cl ; print cl
add dl, '0'
int 21h
mov ah, 02h
mov dl, '+' ; print '+'
int 21h
mov ah, 02h
mov dl, bl ; print bl
add dl, '0'
int 21h
mov ah, 02h
mov dl, '=' ; print '='
int 21h
mov ah, 02h
mov dl, ris
add dl, '0'
int 21h
mov ah, 4Ch
int 21h ; Return to DOS
main endp
somma proc near
push bp ; I store the base pointer in the stack
mov bp, sp ; copy in bp the address of the stack pointer in this moment
; momento, cioè quando inizia la procedura.
sub sp, 2 ; I save 2 bytes for a local variable
push cx ; I save these two registers because I want to use them as
push dx ; registers for my local parameters, then they will be restored
; DEBUG
xor ax, ax
mov ax, [bp] ; Initial stored address of bp
mov ax, [bp + 2] ; Address of the instruction following the call
mov ax, [bp + 4] ; The value I had put from cx
mov ax, [bp + 6] ; The value I had put from bx
; END DEBUG
mov cx, [bp + 4]
mov dx, [bp + 6]
mov [bp - 2], cx
add [bp - 2], dx
mov ax, [bp - 2]
pop dx
pop cx
mov sp, bp
pop bp
ret
somma endp
end main
