Monkleys Monkleys - 1 month ago 11
C Question

Assembly intel x86 which addresses can be used to define arguments

Which memory points can I actually use?
I have this assembly code to power(a,b) by recursion:

int power(int x, int y); *
;*****************************************************************************
%define x [ebp+8]
%define y [ebp+12]
power:
push ebp
mov ebp, esp

mov eax, y ;move y into eax
cmp eax, 0 ;compare y to 0
jne l10; ;if not equal, jump to l10
mov eax, 1 ;move 1 into eax
jmp l20; ;jump to l20, the leave, ret label

l10:
mov eax, y ; move y into eax
sub eax, 1 ; y-1
push eax ; push y-1 onto stack
mov ebx, x ; move x into ebx
push ebx ; push x onto stack
call power ; call power/recursion
add esp, 8 ; add 8 to stack(4*2) for the two vars
imul eax, x ; multiply the returned value from call by x

l20:
leave ; leave
ret ;ret


It's coded straight from this c code:

int power_c(int x, int y) {
if (y == 0) {
return 1;
} else {
return power_c(x, y - 1)*x;
}
}


The asm code works perfectly, any suggested adjustments would be great, I'm still new to assembly. My question is, which addresses can I actually use to define arguments? Here, I have two, and I use:

%define x [ebp+8]
%define y [ebp+12]


If I have more, do I just increase it? Lets say all are ints, 4bytes, like so?

%define x [ebp+8]
%define y [ebp+12]
%define z [ebp+16]
%define a [ebp+20]
%define b [ebp+24]


I've hit a snag with code where I need to define more arguments, I just can't figure this out, any help would be greatly appreciated.

Answer

Arguments are passed on the stack - the caller is responsible for pushing them. The space is already reserved when your function starts. If you changed your prototype to power_c(int x, int y, int z), then z would be at [ebp+16].

Local Variables (or automatics) are your responsibility. The standard way is to subtract the space you need from esp, as @Peter Cordes mentions in the comments. So to create variable a and b, you would do:

sub esp, 8
%define a [ebp+4]
%define b [ebp-8]

Note that at this point ebp == esp+8. We define the variables relative to ebp, not esp, so that you can continue to use push and pop instructions (which change the stack pointer). Remember to set esp back to ebp (mov esp, ebp) before you exit the function, so that the return address is found correctly.

Comments