用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

前提知识

  c0s调用main函数的地址:  11ah

  main函数的连接地址:  01fah

一、全局变量与局部变量

测试程序

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
int a1,a2,a3;

void f(void);
void g(void);
void h(void);
main()
{
    int b1,b2,b3;
    a1 = 0xa1;a2 = 0xa2;a3 = 0xa3;
    b1 = 0xb1;b2 = 0xb2;b3 = 0xb3;
}

void f(void)
{
    int c1,c2,c3;
    a1 = 0x0fa1;a2 = 0x0fa2; a3 = 0x0fa3;
    c1 = 0xc1; c2 = 0xc2; c3 = 0xc3;
    c1 = c2 + c3;
}

void g(void)
{
    int i = 100;
    while(i--);
}

void h(void)
{
    int h1,h2,h3,h4,h5,h6,h7;
    h1 = 0xc1; h2 = 0xc2; h3 = 0xc3;h4 = 0xc4;
    h5 = 0xc5; h6 = 0xc6; h7 = 0xc7;
    h1 = h2 + h3;
    h2 = h3 + h4;
}
View Code

编译、连接后,用debug调试这段代码,根据函数分别贴出对应的反汇编代码

1、main函数

(1)全局变量

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
main()
{
    int b1,b2,b3;
    a1 = 0xa1;a2 = 0xa2;a3 = 0xa3;
    b1 = 0xb1;b2 = 0xb2;b3 = 0xb3;
}
用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

对应的反汇编代码

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

  可以看到全局变量,a1、a2、a3的地址分别是ds:[01a6]、ds:[01a8]、ds:[01aa]。用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

  可以看到,ds:[01a6]的物理地址是16266h,而程序的结束位置是CS:[2a0]的物理地址是15d60。可见,全局变量位于代码段外。ds=ss,而sp=ffe6,ss:sp的物理位置为260a6h,即栈顶位于260a6h,栈应高于栈顶。所以全局变量不可能位于栈区。

    综上所述,我认为全局变量位于非代码段,非栈段,而位于data段(初始化)或者bss段(未初始化)。

(2)局部变量

 开辟在栈中的局部变量 

  a) 编译器先将BP压入栈

  b)用BP保存栈指针,然后SP-6,为局部变量开辟空间。

    push bp

    mov bp,sp

    sub sp,+6

  c) 函数返回前恢复栈,释放局部变量空间

    mov sp,bp

  d) 恢复BP

2、f函数

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
void f(void)
{
    int c1,c2,c3;
    a1 = 0x0fa1;a2 = 0x0fa2; a3 = 0x0fa3;
    c1 = 0xc1; c2 = 0xc2; c3 = 0xc3;
    c1 = c2 + c3;
}
用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

  对应的反汇编代码

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

  局部变量c1、c2被开辟在寄存器SI、DI中,而c3则开辟在栈中。

  开辟在寄存器中的局部变量 

  a) 编译器先将BP压入栈

  b)用BP保存栈指针,将SI、DI压入栈,从而为局部变量开辟空间

    push bp

    mov bp,sp

    push si

    push di

  c) 函数返回前恢复寄存器(释放局部变量),然后恢复栈

    pop di

    pop si

    mov sp,bp

  d) 恢复BP

  无论开辟到栈中,还是开辟在寄存器中,栈指针的移动都是相同的。

3、g函数

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
void g(void)
{
    int i = 100;
    while(i--);
}
用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

  对应的反汇编代码

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

  通过这个函数的反汇编可以重复验证“开辟在寄存器中的局部变量”的结论。

4、h函数

 还会开辟到其他地方吗?

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
void h(void)
{
    int h1,h2,h3,h4,h5,h6,h7;
    h1 = 0xc1; h2 = 0xc2; h3 = 0xc3;h4 = 0xc4;
    h5 = 0xc5; h6 = 0xc6; h7 = 0xc7;
    h1 = h2 + h3;
    h2 = h3 + h4;
}
用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

 对应的反汇编代码

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

  可以看到,当有7个局部变量的情况下,局部变量除了开辟在栈中,就是寄存器中,没别的地方了

 什么时候开辟在栈中,什么时候开辟在寄存器中?这个问题还搞不懂,不过感觉没多大意义。

二、函数如何传递形式参数,又是如何接受的呢

  测试程序

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
void showchar(char a,char b);

main()
{
    showchar(a,2);
}

void showchar(char a,char b)
{
    char r;
    r  = a;
    r  = b;
}
用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

1、main函数

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
main()
{
    showchar(a,2);
}
用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

对应的反汇编代码

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

a) 函数的参数是通过栈传递,而且是从右到左依次入栈

b) 即使是char型变量,在传递参数时,也是占用两个字节,因为push操作是两个字节为单位的。取的时候,是按照它的类型来的

c) 释放形式参数可以通过多次pop来实现。事实上,有时是通过“add sp,+数值”来实现的。显然,后者释放空间来的更快。

2、showchar函数

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
void showchar(char a,char b)
{
    char r;
    r  = a;
    r  = b;
}
用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

对应的反汇编代码

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

d) 调用函数前后堆栈保持一致,也就是函数返回时要让堆栈指针恢复到和进入函数时一样的状态

e) 函数接受形参是通过从栈中取的

f) 对于为初始化的局部变量,编译器是不会给它赋初值的,而是拿来就用

g) main函数的局部变量的寿命要比调用函数showchar的形参寿命长

h) BP不仅保存了堆栈的值,而且通过它可以找到传入参数的值,BP+4是第一个参数,BP+6是第二个参数......取参数是从左到右取的(这就是堆栈的妙处)

三、函数返回值

 测试程序

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
char f(void);

main()
{
    char c;
    c = f();
}

char f(void)
{
    return a;
}
View Code

1、main函数

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
char f(void);

main()
{
    char c;
    c = f();
}
用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

对应的反汇编代码

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

2、f函数

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里
char f(void)
{
    return a;
}
用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

对应的反汇编代码

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

函数返回值:

  char型 AL

  int型 AX  

四、总结

1、全局变量

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里,布布扣,bubuko.com

用汇编语言研究C语言的全局变量、局部变量、形式参数、返回值放在哪里

上一篇:一个好用的hash函数(C语言)


下一篇:从网页下载配置文件