汇编3-返回以及优化

正如前文所说,函数返回值会被存入EAX等寄存器,然后返回后由程序从中读取。但如果返回值较大呢?

开始博主打算用double测试,后来发现这个要用到x87这套完全不同的指令集。只好用结构体了。构造C程序

#include <stdio.h>

struct myrd{

    int i;

    int j;

    int k;

};

struct myrd myrdfunc(){

    struct myrd myrd1;

    myrd1.i = 1;

    myrd1.j = 2;

    myrd1.k = 3;

    return myrd1;

}

int main(){

    struct myrd myrd2;

    myrd2 = myrdfunc();

}

  

在两个函数入口处设置断电。在myrdfunc()入口处(call语句前)可看到

00BB36E8 8D 85 18 FF FF FF lea eax,[ebp+FFFFFF18h]

00BB36EE 50 push eax

  

由此可见为了返回专门开辟了一块内存区域并将地址存入了EAX。记录EAX的值。进入函数。观察该段

00BB3CDD 8B 45 08 mov eax,dword ptr [ebp+8]

00BB3CE0 8B 4D EC mov ecx,dword ptr [ebp-14h]

00BB3CE3 89 08 mov dword ptr [eax],ecx

00BB3CE5 8B 55 F0 mov edx,dword ptr [ebp-10h]

00BB3CE8 89 50 04 mov dword ptr [eax+4],edx

00BB3CEB 8B 4D F4 mov ecx,dword ptr [ebp-0Ch]

00BB3CEE 89 48 08 mov dword ptr [eax+8],ecx

00BB3CF1 8B 45 08 mov eax,dword ptr [ebp+8]

  

检查ebp+8的值,恰为eax。而通过ecx,edx将三个值分别存到eax所指向的内存区域。最后将ebp+8的值重新复制给eax。之后函数返回。

跳转回main后第一条语句为

00BB36F4 83 C4 04 add esp,4

观察esp+4的值,恰为刚才压入栈中的eax,此操作将清栈。

之后便是从eax中取回函数的返回值。

00BB36F7 8B 08 mov ecx,dword ptr [eax]

00BB36F9 89 4D EC mov dword ptr [ebp-14h],ecx

00BB36FC 8B 50 04 mov edx,dword ptr [eax+4]

00BB36FF 89 55 F0 mov dword ptr [ebp-10h],edx

00BB3702 8B 40 08 mov eax,dword ptr [eax+8]

00BB3705 89 45 F4 mov dword ptr [ebp-0Ch],eax

  

由于main中没有其他操作,而局部变量的生存期又很短,我们猜想这些代码是不是冗余呢?

将debug改为release

此时debug:

生成程序只有两行,没有任何冗余。由此可见debug和release程序的用途完全不同。

时间: 2024-10-19 17:11:07

汇编3-返回以及优化的相关文章

转:C++中临时对象及返回值优化

http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象. 通常出现在以下两种情况: (1)为了使函数调用成功而进行隐式类型转换的时候. 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁.如下例: //计算字符ch

[转] C++中临时对象及返回值优化

http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象. 通常出现在以下两种情况: (1)为了使函数调用成功而进行隐式类型转换的时候. 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁.如下例: //计算字符ch

C++返回值优化RVO

返回值优化,是一种属于编译器的技术,它通过转换源代码和对象的创建来加快源代码的执行速度.RVO = return value optimization. 测试平台:STM32F103VG + Keil 5.15 背景:我们有个MacAddress::ToArray byte* MacAddress::ToArray() const { return (byte*)&Value; } 因为封装需要,打算返回字节数组类ByteArray的对象,于是有 ByteArray MacAddress::To

C++返回值优化

返回值优化(Return Value Optimization,简称RVO)是一种编译器优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用于返回,那么这个临时对象会消耗一个构造函数(Constructor)的调用.一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价. 经过返回值优化,就可以将成本降低到一个构造函数的代价.这样就省去了一次拷贝构造函数的调用和依次析构函数的调用. 例子如下: class MyString {

命名的返回值优化(Named Return Value optimization (NRVO))

命名的返回值优化: 针对返回一个局部的变量的优化,可以直接用返回的结果对象直接替代局部变量,从而减少了一个复制拷贝,从而提高效率. 比如 一个函数如下: X bar() { X xx; // .. 处理xx return xx; } 而在编译器看来则是如下的代码: // 此处的_result是一个在调用该函数时产生的一个临时对象 // , 然后将该对象传入,用以接受结果 void bar(X & __result) { X xx; // 调用xx的构造函数 xx.X::X(); // .. 处理

More Effective C++----(20)协助完成返回值优化

Item M20:协助完成返回值优化 一个返回对象的函数很难有较高的效率,因为传值返回会导致调用对象内的构造和析构函数(参见条款M19),这种调用是不能避免的.问题很简单:一个函数要么为了保证正确的行为而返回对象要么就不这么做.如果它返回了对象,就没有办法摆脱被返回的对象.就说到这. 考虑rational(有理数)类的成员函数operator*:(返回类型为const是为了防止连续对操作符的操作,一是返回的对象是一个临时对象,多个操作是在其临时对象上的操作,二是不符合内置类型的要求) class

网站安全狗”响应内容保护“网页错误返回页面优化功能介绍

网站安全狗最新版本(主程序版本号:3.2.08157)在“资源保护”模块多了一个功能叫做:响应内容保护.如下图所示: <ignore_js_op> 该模块的主要功能是,当我们访问网站时,不合理的访问,或者网站自身的问题,会出现各种的错误返回页面.从安全的角度上讲,这就可以给攻击者提供判断的依据,为了防止这种情况,网站安全狗对网页错误的返回页面做了优化处理,并将此资源进行了回收利用,加入了百度推广的相关广告信息. <ignore_js_op> 该页面的推广信息为您搜索的相关类似信息.

从汇编看尾递归的优化

对于尾递归,很多人的理解仅局限于它是递归和尾调用的一个合体,比普通递归效率高.至于效率为什么高,高在哪,可能没有深究过. 尾调用 要说尾递归,得先说尾调用.我理解的尾调用大概是这么一种情况:k7娱乐城 函数A里面调用了函数B. 函数B执行后,函数A马上返回. 也就是说调用函数B(并返回执行结果)是函数A所做的最后一件事. 相当于执行完函数B后,函数A也就执行完. 因此在执行函数B时,函数A的栈帧其实是已经大部分没用了,可以被修改或覆盖.编译器可以利用这一点进行优化,函数B执行后直接返回到函数A的

参数返回值及NRV优化(named return value optimization)

C++11中的移动构造函数又把NRV优化翻出来了,都是采用临时中间值优化,两者不能共存. 参数传递如何实现? [实现模型1]引入临时对象,使用拷贝构造函数初始化.然后利用bitwise copy将其拷贝到x0的位置.比如: void foo( X x0 ); X xx; foo( xx ); 改写成 X __temp0; __temp0.X::X ( xx ); foo( __temp0 );还有一件事需要做,修改foo的声明,可以避免bit-wise copy的那一步. void foo( X