Perica Senjak wrote:
Ok, in a function, when a register gets pushed onto the stack (To save it's value); Where do i start geting the previously pushed arguments? What i mean by this is, if i had a function like this
Code:
_Add:
push bp
push ax
push bx
mov bp, sp
mov ax, [bp + 8] ;This is what i got a guestion about,
mov bx, [bp + 10] ;and this aswell!
add ax, bx
pop bx
pop ax
pop bp
ret
Alright, my question is, when the registers are pushed onto the stack, the registers are 2 bytes in size right? so i count up the registers pushed, bp, ax, bx = 6 bytes! So i start retrieving the first argument at 8 bytes (Do you understand what i'm saying?) BUT, if i was in Protected Mode; The PM (Protected Mode) Registers are double the size of the RM ones, right? So if i pushed ebp, eax, ebx onto the stack, would they take up 12 bytes? (Since they are double the size of RM Registers?) If they do take up 12 bytes, would i need to start retrieving the arguments at 14 bytes?
Given the design of the code as it is, you would actually be starting at [EBP+16] (that is 12 + 4); in p-mode, PUSH and POP always operate on a doubleword at a time. However, it is conventional to set the EBP
before pushing any other registers for saving, which would place the first argument at [EBP + 8] consistently.
There is also a bug in your code, and I am quite sorry to say I missed it earlier. By restoring AX (or, in p-mode, EAX and EBX), you are overwriting the return value in AX, so that the function has no effect other than to consume cycles and memory.
IIRC, the gcc calling convention is that EBP, ESP, EBX, EDI and ESI
must be saved and restored by the called function if they are used during the function's operation; conversely, it is assumed that EAX and EDX, which are used to return values, are trashed even if there is no return value. Other registers are assumed to be volatile; saving them is a good procatice, but not strictly, necessary, AFAICT. If anyone knows differently, please et me know.
HTH.