zoukankan      html  css  js  c++  java
  • gcc处理函数调用时的PUSH解决办法

    一般的调用函数格式是:

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    ;function1

    ........................

    push param1

    push param2  

    call function2

     .............................

     >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    ;function2

    .......................

    push ebp

    mov ebp, esp

    ;以后使用时候,只需

    mov eax, [ebp+8] ;eax=param2。为何不是ebp+4?因为[ebp+4]是function2返回后的执行地址

    mov edx, [ebp+0c] ; eax=param1。

    今天学习了一下GCC编辑器。我使用的version是:

    e:>gcc   -v

    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=e:/mingw/bin/../libexec/gcc/mingw32/4.5.2/lto-wrapper.exe
    Target: mingw32
    Configured with: ../gcc-4.5.2/configure --enable-languages=c,c++,ada,fortran,objc,obj-c++ --disable-sjlj-exceptions --wi
    th-dwarf2 --enable-shared --enable-libgomp --disable-win32-registry --enable-libstdcxx-debug --enable-version-specific-r
    untime-libs --disable-werror --build=mingw32 --prefix=/mingw
    Thread model: win32

    gcc version 4.5.2 (GCC) 

    GCC编译器在调用函数时,没有使用PUSH。而是在调用函数里面多申请了2个局部变量(假设被调用函数使用2个参数)。然后用mov的方式,把参数mov到这2个局部变量上。

    看起来像这样(以下代码使用的是一段简单的c代码的反汇编,功能是:输入2个数,打印最大的那个数)。

    ;function1:

    .text:004013C0 formatString= dword ptr -20h 参数传递变量3
    .text:004013C0 param2= dword ptr -1Ch ;参数传递变量2
    .text:004013C0 param1= dword ptr -18h 参数传递变量1。注意,这个是gcc为了参数传递时开始申请的变量
    .text:004013C0 number2= dword ptr -0Ch ;我们需要使用的局部变量3
    .text:004013C0 number1= dword ptr -8       ;我们需要使用的局部变量2
    .text:004013C0 maxNumber= dword ptr -4  ;我们需要使用的局部变量1
    .text:004013C0

    ;例行程序 

    .text:004013C0 push    ebp
    .text:004013C1 mov     ebp, esp

    ;开始为局部变量弄空间 

    .text:004013C3 and     esp, 0FFFFFFF0h
    .text:004013C6 sub     esp, 20h

    ; SEH等。GCC自动添加的

    .text:004013C9 call    sub_401A60

    ;好戏开始了 

    .text:004013CE lea     eax, [esp+20h+number2] ;请注意:esp+20h=ebp,但是人家不用ebp-0ch
    .text:004013D2 mov     [esp+20h+param1], eax ;看见没有,这个就相当于  push eax
    .text:004013D6 lea     eax, [esp+20h+number1]

    .text:004013DA mov     [esp+20h+param2], eax  ;同理,push eax

    .text:004013E5 call    scanf ;调用参数了。
    .text:004013EA mov     edx, [esp+20h+number2]
    .text:004013EE mov     eax, [esp+20h+number1]
    .text:004013F2 mov     [esp+20h+param2], edx ;又开始将两个参数压入栈了。  push edx
    .text:004013F6 mov     [esp+20h+formatString], eax ;push eax
    .text:004013F9 call     findmaxnumber ;findmaxnumber函数时我们自己实现的。我们将其代码贴出来。见下面。

    ;同样的处理方式,和上面的2个调用方法一样。 

    .text:004013FE mov     [esp+20h+maxNumber], eax
    .text:00401402 mov     eax, [esp+20h+maxNumber]
    .text:00401406 mov     [esp+20h+param2], eax
    .text:0040140A mov     [esp+20h+formatString], offset aMaxD ; "max=%d"

    .text:00401411 call    printf 

     ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    ;子函数:findmaxnumber( number1, number2) 

    .text:00401418 maxNumber= dword ptr -4

    .text:00401418 number1= dword ptr  8 ;这个就使用了栈中的传递过来的参数1
    .text:00401418 number2= dword ptr  0Ch ;传递参数2
    .text:00401418
    .text:00401418 push    ebp
    .text:00401419 mov     ebp, esp
    .text:0040141B sub     esp, 10h
    .text:0040141E mov     eax, [ebp+number1]
    .text:00401421 cmp     eax, [ebp+number2]
    .text:00401424 jle     short loc_40142E
    .text:00401426 mov     eax, [ebp+number1]
    .text:00401429 mov     [ebp+maxNumber], eax
    .text:0040142C jmp     short loc_401434
    .text:0040142E ; ---------------------------------------------------------------------------
    .text:0040142E
    .text:0040142E loc_40142E:                   ; CODE XREF: sub_401418+Cj
    .text:0040142E mov     eax, [ebp+number2]
    .text:00401431 mov     [ebp+maxNumber], eax
    .text:00401434
    .text:00401434 loc_401434:                   ; CODE XREF: sub_401418+14j
    .text:00401434 mov     eax, [ebp+maxNumber] ;最后把结果放在eax里面返回
    .text:00401437 leave
    .text:00401438 retn
    .text:00401438 sub_401418 endp
    .text:00401438
    .text:00401438 ; ---------------------------------------------------------------------------

    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    总结:

    GCC编译时,被调用函数是没有什么变化的。和vs的编译器不同的是在调用函数里面,子函数使用几个参数传递,在调用函数里面就就多申请几个局部变量,然后调用函数将数据放入这些局部变量里面。形如:mov   [ebp-18], eax,这个就相当于push eax了。

    达到了参数传递的目的。 

  • 相关阅读:
    hdu acm 2844 Coins 解题报告
    hdu 1963 Investment 解题报告
    codeforces 454B. Little Pony and Sort by Shift 解题报告
    广大暑假训练1 E题 Paid Roads(poj 3411) 解题报告
    hdu acm 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
    hdu acm 1114 Piggy-Bank 解题报告
    poj 2531 Network Saboteur 解题报告
    数据库范式
    ngnix 配置CI框架 与 CI的简单使用
    Vundle的安装
  • 原文地址:https://www.cnblogs.com/keepfocus/p/2176420.html
Copyright © 2011-2022 走看看