参数、局部变量、返回值

  1. 返回值是如何传递的
  2. 参数传递的本质
  3. 局部变量的内存分配

返回值是如何传递的

函数是怎么把返回值存到某个地方的,在函数外面是怎么得到这个返回值的,对应汇编代码

函数的返回值是:

  • 8位,用al返回
  • 16位,用ax返回
  • 32位,用eax返回

返回值超过32位时,存在哪里?

int64 Function(){						
    __int64 x = 0x1234567890;					
    return x;					
}		

对应汇编

mov dword ptr [ebp-8],eax
mov dword ptr [ebp-4],edx

用eax、edx两个寄存器,且eax存低位34567890h,edx存高位12h。

参数传递的本质

两种传递方式:用堆栈和用寄存器。

1字节、2字节、4字节等整数类型的参数一律按4字节(本机尺寸)传递,但在使用的时候仍会按定义的字节来使用,如:

void fun(char a){
    int b = a;
    //对应汇编:
    //movsx       eax,byte ptr [ebp+8]
    //mov         dword ptr [ebp-4],eax
    //会进行扩展
}
int main(){
    fun(1);
}

按本机尺寸传递参数效率最高。

再来以编译器的角度看待一个老问题:改变形参的值不影响实参:

void fun(int x){
    x = x + 1;
}
int main(){
    int x = 2;
    fun(x);
    printf("%d",x);
}

很显然上面代码输出的值是2。

首先在main里,2的值是存在了[ebp-4]上,传参的时候也仅是将[ebp-4]上的值复制了一份再传递给fun函数,所以你对复制的这个值怎么操作也影响不到[ebp-4]上的大小。

局部变量的内存分配

对于char、short、int型等小于本机尺寸的局部变量,内存会分配本机尺寸字节数(32位–4字节)。

而但对于char、short、int型数组变量,内存则会分配对应大小字节空间,如:

假设对于空函数,内存默认分配40h

若定义char a[4] = {0},则会分配44h(根据本机尺寸,char a[3] = {0},同样分配44h)

若定义short a[4] = {0},则会分配48h

参数与局部变量其实没有本质区别,都是在堆栈中分配的空间。如果严谨点说区别,那就是,参数是函数调用时分配的,而局部变量是函数执行时分配的。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1666739907@qq.com
github