C 可用于定义参数的汇编英特尔x86地址

C 可用于定义参数的汇编英特尔x86地址,c,assembly,nasm,C,Assembly,Nasm,我可以实际使用哪些记忆点? 我有一个通过递归为(a,b)提供动力的汇编代码: int power(int x, int y); * ;***************************************************************************** %define x [ebp+8] %define y [ebp+12] power: push eb

我可以实际使用哪些记忆点? 我有一个通过递归为(a,b)提供动力的汇编代码:

 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
它的代码直接来自c代码:

int power_c(int x, int y) {
    if (y == 0) {
        return 1;
    } else {
        return power_c(x, y - 1)*x;
    }
}
asm代码工作得很好,任何建议的调整都会很好,我对汇编还是新手。我的问题是,我可以使用哪些地址来定义参数?在这里,我有两个,我使用:

%define x [ebp+8]
%define y [ebp+12]
如果我有更多,我会增加吗?假设所有的都是整数,4字节,像这样吗

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

我在代码中遇到了一个障碍,我需要定义更多的参数,我就是想不出这一点,如果有任何帮助,我将不胜感激。

参数在堆栈上传递-调用方负责推送它们。当函数启动时,空间已被保留。如果您将原型更改为
power\u c(intx,inty,intz)
,那么z将位于
[ebp+16]

局部变量(或自动变量)由您负责。标准方法是从
esp
中减去所需的空间,正如@Peter Cordes在评论中提到的那样。因此,要创建变量
a
b
,您需要执行以下操作:

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

请注意,此时ebp
ebp
=
esp+8
。我们定义了与
ebp
相关的变量,而不是
esp
,以便您可以继续使用push和pop指令(这会更改堆栈指针)。请记住在退出函数之前将
esp
设置回
ebp
mov-esp,ebp
),以便正确找到返回地址。

x和y是函数参数,而不是局部变量。他们被区别对待,我明白了。我从没想过他们有什么不同。感谢您澄清这一点。若要为EBP以下的局部变量保留堆栈空间,请在函数的开头使用
sub esp,24
或其他任何内容,并在返回之前将其反转。提示:为标签使用有意义的名称
jmp尾声
告诉您所有
jmp l20;跳转到l20,left,ret标签可以,不需要注释。或者,这个评论可以解释你为什么要这么做。类似地,
mov-eax,1;将1移动到eax
是一个无用的注释。不要试图解释你刚学到的东西。类似于
的注释返回1,因为…
会更有用。@AShelly从技术上讲,参数是局部变量。例如,您可以修改它们。它们之间的区别是,被调用函数在返回地址下方为局部变量分配空间,调用方在调用之前在返回地址上方为参数分配并初始化空间。很好地解释了这个方案。