懂C++和汇编的朋友进

we_sky2008 2010-04-27 12:20:46
参数传递的过程不是很明白
我们还没学到汇编语言,看的不是很明白
麻烦大家解释下汇编代码,谢谢大家!

//C++代码:
#include<iostream>

using namespace std;

class A
{
public:
A(int x = 0) : a(x){cout<<"normal"<<endl;}
A(const A &ref) : a(ref.a){cout<<"copy"<<endl;}
int a;
};

void test(A x)
{
}

int main()
{
A a;

test(a);
system("pause");
return 0;
}


//汇编代码:
17: int main()
18: {
004011B0 push ebp
004011B1 mov ebp,esp
004011B3 sub esp,48h
004011B6 push ebx
004011B7 push esi
004011B8 push edi
004011B9 lea edi,[ebp-48h]
004011BC mov ecx,12h
004011C1 mov eax,0CCCCCCCCh
004011C6 rep stos dword ptr [edi]
19: A a;
004011C8 push 0
004011CA lea ecx,[ebp-4] //ecx传递this指针?
004011CD call @ILT+10(A::A) (0040100f) //构造局部对象a
20:
21: test(a);
004011D2 push ecx //传递拷贝构造函数的引用参数 即对象a的地址
004011D3 mov ecx,esp //这条语句是干嘛的? 为形参分配空间?
004011D5 lea eax,[ebp-4]
004011D8 push eax //这条语句的作用是什么? 构造形参的话this指针有了,参数也有了,怎么此处又将a的地址入栈?
004011D9 call @ILT+150(A::A) (0040109b) //在ecx指向的空间以已经压栈的a的地址做引用参数拷贝构造形参?
004011DE call @ILT+180(test) (004010b9) //
004011E3 add esp,4
22: system("pause");
004011E6 push offset string "pause" (0043101c)
004011EB call system (00409140)
004011F0 add esp,4
23: return 0;
004011F3 xor eax,eax
24: }


13: void test(A x)
14: {
00401180 push ebp
00401181 mov ebp,esp
00401183 sub esp,40h
00401186 push ebx
00401187 push esi
00401188 push edi
00401189 lea edi,[ebp-40h]
0040118C mov ecx,10h
00401191 mov eax,0CCCCCCCCh
00401196 rep stos dword ptr [edi]
15: }
00401198 pop edi
00401199 pop esi
0040119A pop ebx
0040119B mov esp,ebp
0040119D pop ebp
0040119E ret
...全文
415 43 打赏 收藏 转发到动态 举报
写回复
用AI写文章
43 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2010-04-29
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 luxiaolai861227 的回复:]
懂C不懂汇编
[/Quote]
懂做馒头不懂磨面粉
we_sky2008 2010-04-27
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 demon__hunter 的回复:]
Assembly code

19: A a;
004011C8 push 0 ;实际要调用A(int x = 0)这个构造函数,
;这个是默认参数入栈
004011CA lea ecx,[……
[/Quote]

004011D2 push ecx ;将ecx入栈保存

004011D8 push eax ;a作为参数入栈,调用A的拷贝构造函数,
;在esp-4~esp处生成一个临时对象

谢谢!
这两条语句压栈的内容是一样的吧?都是a的地址
做拷贝构造函数的引用参数的话,任意一个就可以了
为什么要压栈两个相同的地址呢?
FrankSun80 2010-04-27
  • 打赏
  • 举报
回复
1. 004011D3 mov ecx,esp //这条语句是干嘛的? 为形参分配空间?

ecx = esp,保留esp,待函数调用完再恢复,因为函数调用中肯定会用到esp.

2. 004011D5 lea eax,[ebp-4]
004011D8 push eax //这条语句的作用是什么? 构造形参的话this指针有了,参数也有了,怎么此处又将a的地址入栈?

这两个语句应该是给参数a分配栈空间。

供参考
机智的呆呆 2010-04-27
  • 打赏
  • 举报
回复

19: A a;
004011C8 push 0 ;实际要调用A(int x = 0)这个构造函数,
;这个是默认参数入栈
004011CA lea ecx,[ebp-4] ;将a对象的地址存入ecx,vc一般this存入ecx
;gcc中this作为最后一参数入栈的,显然ebp-4 ~ebp这段空间就是a的存储空间
004011CD call @ILT+10(A::A) (0040100f) //构造局部对象a
20:
21: test(a);
004011D2 push ecx ;将ecx入栈保存
004011D3 mov ecx,esp ;将esp保存到ecx,说明编译器打算将esp-4~esp
;作为test函数中参数a对应的内存,test传参时要调用A的拷贝构造函数生成一个临时对象
004011D5 lea eax,[ebp-4];将a的地址保存eax
004011D8 push eax ;a作为参数入栈,调用A的拷贝构造函数,
;在esp-4~esp处生成一个临时对象
004011D9 call @ILT+150(A::A) (0040109b)
004011DE call @ILT+180(test) (004010b9) ;由于在上个栈帧顶端esp-4~esp已经生成了一个
;一个临时对象a,所以省去了push操作,直接调用test函数
004011E3 add esp,4
22: system("pause");
004011E6 push offset string "pause" (0043101c)
004011EB call system (00409140)
004011F0 add esp,4
23: return 0;
004011F3 xor eax,eax
24: }

贪食蛇男 2010-04-27
  • 打赏
  • 举报
回复
不是很懂,C到汇编还好说点,C++就更晕了
ldz618 2010-04-27
  • 打赏
  • 举报
回复
汇编。。。不懂。。曾经就很厌恶这门科,,想当年差点挂科。。杯具
ldz618 2010-04-27
  • 打赏
  • 举报
回复
汇编。。。不懂。。曾经就很厌恶这门科,,想当年差点挂科。。杯具
we_sky2008 2010-04-27
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jackyjkchen 的回复:]
自己注释了那么多了,也差不多了吧
[/Quote]
恩,大体过程知道了
下面这句还没看懂:

004011D8 push eax //这条语句的作用是什么? 构造形参的话this指针有了,参数也有了,怎么此处又将a的地址入栈?
jackyjkchen 2010-04-27
  • 打赏
  • 举报
回复
自己注释了那么多了,也差不多了吧
we_sky2008 2010-04-27
  • 打赏
  • 举报
回复
C++也是到大二下学期才开选修课程
我现在先自学下,明年准备选修C++
we_sky2008 2010-04-27
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 zhao4zhong1 的回复:]
现在赶快亡羊补牢还来得及
[/Quote]
我们大二才开汇编的课程
还没开始看汇编的书
赵4老师 2010-04-27
  • 打赏
  • 举报
回复
现在赶快亡羊补牢还来得及
we_sky2008 2010-04-27
  • 打赏
  • 举报
回复
自己先顶下
大家快来啊
我结贴很快的!
patricxuqi 2010-04-27
  • 打赏
  • 举报
回复
值传递的时候才借助堆栈的;换作引用或者指针就直接用寄存器了。建议楼主把代码编译成release的时候再看看产生的汇编代码。
处处留心 2010-04-27
  • 打赏
  • 举报
回复
懂C不懂汇编
aleyn 2010-04-27
  • 打赏
  • 举报
回复
到现在学了,c++和汇编,感觉汇编真的没有学到什么东西,自己学到的只是皮毛
机智的呆呆 2010-04-27
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 we_sky2008 的回复:]

引用 28 楼 demon__hunter 的回复:
004011D2 push ecx ;将ecx入栈保存
这条指令跟拷贝构造函数调用没啥关系,因为下面ecx被修改了,这条指令只是保存修改之前的ecx的值。
在vc下,成员函数调用参数从右到左入栈,this存入ecx。
push eax;才是参数入栈, mov ecx,esp 则是保存this指针

呵呵
多谢你了
不过我觉得此……
[/Quote]
确实此处push ecx;相当于是为test函数参数入栈的。
后面的临时对象霸占了保存ecx的位置。
函数参数入栈时 基本是push 操作,push 操作
在栈上为参数分配空间同时并有个初始化过程,而通过直接调节esp为形参分配空间,
随后还得初始化操作,ms这样效率比较低。
kakam 2010-04-27
  • 打赏
  • 举报
回复
支持10楼
we_sky2008 2010-04-27
  • 打赏
  • 举报
回复
上面两个图形显示有问题,重新发

[Quote=引用 35 楼 we_sky2008 的回复:]

//esp 1-----------1
// 1 &a 1 -->004011D8 push,eax //此处为拷贝构造函数的参数
// 1-----------1
// 1 &a 1 -->004011D2 push,ecx //此处创建形参 里面为什么要存储&a呢?只开辟空间就够了 莫非只是简单的使栈往上增长(move ecx,esp)开辟空间存放形参?
// 1-----------1
// 1 1
// 1 . 1
// 1 . 1
// 1 . 1
// 1 . 1
// 1 1
// 1 1
// 1-----------1
// 1 局部对象a 1
// 1-----------1 -->ebp


[/Quote]
如果是这样的话,只用sub esp,4就可以了啊
没必要使用push指令吧?
OnMyWay2010 2010-04-27
  • 打赏
  • 举报
回复
看不懂汇编
呵呵
加载更多回复(23)

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧