newlyh1992 发表于 2020-4-27 12:08:11

call 参数push问题。

想问各位大佬,
当call一个函数传参数的时候,先将参数push入栈,当函数调用的完成之后,只需要将栈平衡就可以,不需要将参数数pop出栈。但是在c中实参在函数调用完成之后实参的值就会被还原,这是不是就意味着实参push栈中,还是会把实参在pop出来吧?还是说在去内存中把之前的实参变量值在读一遍?
小弟刚刚看汇编求大佬解答!!

newlyh1992 发表于 2020-4-27 12:09:02

自顶一下哈

人造人 发表于 2020-4-27 12:35:26

都已经学了汇编语言了,那就给你一个代码,自己看
自己去分析堆栈上面的参数是如何传递的

int main(void) {
00DC1810push      ebp
00DC1811mov         ebp,esp
00DC1813sub         esp,0D8h
00DC1819push      ebx
00DC181Apush      esi
00DC181Bpush      edi
00DC181Clea         edi,
00DC1822mov         ecx,36h
00DC1827mov         eax,0CCCCCCCCh
00DC182Crep stos    dword ptr es:
00DC182Emov         ecx,offset _8A2E5209_main@c (0DCC003h)
00DC1833call      @__CheckForDebuggerJustMyCode@4 (0DC1217h)
    int a = 12;
00DC1838mov         dword ptr ,0Ch
    int b = 13;
00DC183Fmov         dword ptr ,0Dh
    test(a, b);
00DC1846mov         eax,dword ptr
00DC1849push      eax
00DC184Amov         ecx,dword ptr
00DC184Dpush      ecx
00DC184Ecall      _test (0DC1389h)
00DC1853add         esp,8
    return 0;
00DC1856xor         eax,eax
}

void test(int a, int b) {
00DC1F70push      ebp
00DC1F71mov         ebp,esp
00DC1F73sub         esp,0C0h
00DC1F79push      ebx
00DC1F7Apush      esi
00DC1F7Bpush      edi
00DC1F7Clea         edi,
00DC1F82mov         ecx,30h
00DC1F87mov         eax,0CCCCCCCCh
00DC1F8Crep stos    dword ptr es:
00DC1F8Emov         ecx,offset _8A2E5209_main@c (0DCC003h)
00DC1F93call      @__CheckForDebuggerJustMyCode@4 (0DC1217h)
    a = a + 1;
00DC1F98mov         eax,dword ptr
00DC1F9Badd         eax,1
00DC1F9Emov         dword ptr ,eax
    b = b + 1;
00DC1FA1mov         eax,dword ptr
00DC1FA4add         eax,1
00DC1FA7mov         dword ptr ,eax
    printf("%d %d\n", a, b);
00DC1FAAmov         eax,dword ptr
00DC1FADpush      eax
00DC1FAEmov         ecx,dword ptr
00DC1FB1push      ecx
00DC1FB2push      offset string "hello\n" (0DC7B30h)
00DC1FB7call      _printf (0DC1046h)
00DC1FBCadd         esp,0Ch
}



这个是去掉符号名的版本
int main(void) {
00DC1810push      ebp
00DC1811mov         ebp,esp
00DC1813sub         esp,0D8h
00DC1819push      ebx
00DC181Apush      esi
00DC181Bpush      edi
00DC181Clea         edi,
00DC1822mov         ecx,36h
00DC1827mov         eax,0CCCCCCCCh
00DC182Crep stos    dword ptr es:
00DC182Emov         ecx,0DCC003h
00DC1833call      00DC1217
    int a = 12;
00DC1838mov         dword ptr ,0Ch
    int b = 13;
00DC183Fmov         dword ptr ,0Dh
    test(a, b);
00DC1846mov         eax,dword ptr
00DC1849push      eax
00DC184Amov         ecx,dword ptr
00DC184Dpush      ecx
00DC184Ecall      00DC1389
00DC1853add         esp,8
    return 0;
00DC1856xor         eax,eax
}

void test(int a, int b) {
00DC1F70push      ebp
00DC1F71mov         ebp,esp
00DC1F73sub         esp,0C0h
00DC1F79push      ebx
00DC1F7Apush      esi
00DC1F7Bpush      edi
00DC1F7Clea         edi,
00DC1F82mov         ecx,30h
00DC1F87mov         eax,0CCCCCCCCh
00DC1F8Crep stos    dword ptr es:
00DC1F8Emov         ecx,0DCC003h
00DC1F93call      00DC1217
    a = a + 1;
00DC1F98mov         eax,dword ptr
00DC1F9Badd         eax,1
00DC1F9Emov         dword ptr ,eax
    b = b + 1;
00DC1FA1mov         eax,dword ptr
00DC1FA4add         eax,1
00DC1FA7mov         dword ptr ,eax
    printf("%d %d\n", a, b);
00DC1FAAmov         eax,dword ptr
00DC1FADpush      eax
00DC1FAEmov         ecx,dword ptr
00DC1FB1push      ecx
00DC1FB2push      0DC7B30h
00DC1FB7call      00DC1046
00DC1FBCadd         esp,0Ch
}

人造人 发表于 2020-4-27 12:39:15

看懂上面的代码后,再看指针的,去分析堆栈上面的参数
学会学习,多画图,多思考

#include <stdio.h>

void test(int *a) {
    *a += 1;
}

int main(void) {
    int a = 12;
    test(&a);
    printf("%d\n", a);
    return 0;
}

newlyh1992 发表于 2020-4-27 14:22:53

本帖最后由 newlyh1992 于 2020-4-27 14:37 编辑

人造人 发表于 2020-4-27 12:39
看懂上面的代码后,再看指针的,去分析堆栈上面的参数
学会学习,多画图,多思考

如何把参数传递给下一个函数,我知道。
假如
int a(int a){
return a + 1;
}

int main(void){
int a = 1;
a(a);
printf("%d\n", a);
}

问题在,main函数调用a(); 这个是变量a应该会被压栈,当main函数调用完a();时,变量a应该是再从栈中把之前的值进行还原,但是再汇编的代码中,我没有看到pop的指令,只看到一个add esp,4的平衡栈的指令。 那变量a的值是如何还原的呢?

405794672 发表于 2020-4-29 19:04:34

不需要还原好吗!谁告诉你原值push了,它就被删了?它还好好的在那里好吗!你push个ax看看,ax还在不在?何况实参是在内存中的。不动它根本就不会改。
页: [1]
查看完整版本: call 参数push问题。