vc如何返回函数结果及压栈参数


    首先说明,本文的分析对象是运行在IA32平台上的程序,试验用的编译器是Visual C++ 6.0中的cl.exe(Microsoft 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86)。

    IA32程序利用程序堆栈来支持过程(procedure)调用,比如创建局部数据、传递参数、保存返回值信息、保存待今后恢复的寄存器等。为了一个过程调用而分配的堆栈空间称为一个stack frame。最顶层的stack frame由两个寄存器标识:ebp保存stack frame的基址,esp保存栈顶地址,因为在过程执行的时候栈顶寄存器的值会经常变化,所以绝大多数的信息都是通过ebp来相对寻址的。图1描绘了stack frame的基本结构。注意在IA32机器上,栈是向低地址方向增长,所以栈顶的地址值小于等于栈底的地址值。

                   stack "bottom"
                  ________________ ______
                 |                |  |
                 |       .        |  |
                 |                |  |
                 |       .        |  |
                 |                |  |--->Earlier frames
                 |       .        |  |
                 |                |  |
                 |       .        |  |      
    |            |                |  |
    |            |________________|__|___
    |            |       .        |  |
    |            |       .        |  |
    |            |       .        |  |
Decreasing       |________________|  |
 address         |   Argument n   |  |
    |       4m-->|________________|  |
    |   (m为整数) |       .        |  |-->Caller's frame
    |            |       .        |  |
    |            |________________|  |
    |            |   Argument 1   |  |
    |       +8-->|________________|  |
    V            | Return address |  |
            +4-->|________________|__|___
                 |   Saved  ebp   |  |
 Frame Pointer-->|________________|  |
           ebp   |Saved  registers|  |
                 |local  variables|  |
                 |      and       |  |-->Current frame
                 |   temporaries  |  |
                 |________________|  |
                 |    Argument    |  |
                 |   build area   |  |
 Stack pointer-->|________________|__|___
           esp       stack "top"

                        图1

    调用C函数时,不管参数类型如何(包括浮点和struct类型)调用者(caller)负责从右至左将参数依次压栈,最后压入返回地址并跳转到被调函数入口处执行,其中每个参数都要按4字节地址对齐。按照地址来说被传递的参数和返回地址都是位于调用者stack frame中的。如果函数的返回值类型是整型(包括char,short,int,long及它们的无符号型)或指针类型的话,那么就利用EAX寄存器来传回返回值。请看下面的函数:

long foo_long(long offset)
{
   long val = 2006 + offset;
   return val;
}

用 /c /Od /FAsc 的编译选项(下文均同)编译出如下的汇编码:

PUBLIC    _foo_long
_TEXT    SEGMENT
_offset$ = 8
_val$ = -4
_foo_long PROC NEAR

; 38   : {

push    ebp ;保存调用者的stack frame基址
mov     ebp, esp
push    ecx

; 39   :    long val = 2006

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值