惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 子风

Android相关转载帖子 C和C++的存储模式 VS2005配置开发ARM - 子风 c++ 虚析构函数的思考 arm-linux-g++ 下交叉编译libxml2 - 子风 (转)Eclipse代码提示功能设置(Java & C/C++) - 子风 linux下面eclipse的c++配置 VS2008 配置boost 用VS.NET2008打包程序遇到不可恢复的生成错误的解决方案 推荐一个原型的设计软件 Mockups For Desktop Grid++Report——推模式下填充子报表 c# 对象的创建过程 - 子风 Failure sending mail - 子风 XP下IIS错误:Server Application Error css总结 - 子风 asp.net缓存-数据依赖缓存 - 子风 - 博客园 .net 测试工具 .net 发送Email 利用7z来分卷压缩文件
c++ 函数的工作原理
子风 · 2012-11-27 · via 博客园 - 子风

目录

  • 函数传参
  • 结构体作为函数的返回值

1:函数传参

1 int Add(int a,int b)
2 {
3     return a+b;
4 }

     反汇编代码

30:       int i = Add(5,6);
00401078   push        6  ; 参数入栈
0040107A   push        5  ; 参数入栈
0040107C   call        @ILT+5(Add) (0040100a)
00401081   add         esp,8    ;由于push2个参数,esp-8,所以这里esp+8,平衡栈。
00401084   mov         dword ptr [ebp-4],eax  ;eax为函数的返回值

此时内存中栈的内容

0012FF24  81 10 40 00  ..@.  ;Call的下一条指令的内存地址
0012FF28  05 00 00 00  ....  ;参数5
0012FF2C  06 00 00 00  ....  ;参数6
0012FF30  00 00 92 7C         

Add函数

00401030   push        ebp      ; 保存ebp
00401031   mov         ebp,esp  ; 赋值 ebp=esp ,ebp作为栈底
00401033   sub         esp,40h  ; 抬高栈,开辟40h个空间
00401036   push        ebx      ;ebx 入栈
00401037   push        esi      ;esi 入栈
00401038   push        edi      ; edi 入栈
00401039   lea         edi,[ebp-40h]  ;初始化栈40h为C
0040103C   mov         ecx,10h
00401041   mov         eax,0CCCCCCCCh
00401046   rep stos    dword ptr [edi]
8:        return a+b;
00401048   mov         eax,dword ptr [ebp+8]  ;取出参数5
0040104B   add         eax,dword ptr [ebp+0Ch]; 取出参数6,返回值放在eax中

0040104E   pop         edi
0040104F   pop         esi
00401050   pop         ebx
00401051   mov         esp,ebp
00401053   pop         ebp
00401054   ret

栈的内存

00401030   push        ebp      ; 保存ebp
00401031   mov         ebp,esp  ; 赋值 ebp=esp ,ebp作为栈底,ebp = 12ff20

0012FF20  80 FF 12 00  .... ;12ff80是ebp的值,(ebp)
0012FF24  81 10 40 00  ..@. +4
0012FF28  05 00 00 00  .... +8
0012FF2C  06 00 00 00  .... +12
0012FF30  00 00 92 7C 

00401048   mov         eax,dword ptr [ebp+8]  ;取出参数5
0040104B   add         eax,dword ptr [ebp+0Ch]; 取出参数6;

[ebp+8] = 05

[ebp+C] = 06

2. 结构体作为函数的返回值

测试代码:

struct tagTest{
    int m_One ;
    int m_Two;
    int m_Three;
    int m_Four;
};

tagTest RerStruct()
{
    tagTest testRet;
    testRet.m_One = 1;
    testRet.m_Two = 2;
    testRet.m_Three = 3;
    testRet.m_Four = 4;
    return testRet;
}

反汇编代码:

30:       tagTest test;
31:       test = RerStruct();
00401078   lea         eax,[ebp-30h]  ;把ebp-30h的地址压入栈,函数的结构体赋值时候用
0040107B   push        eax
0040107C   call        @ILT+0(RerStruct) (00401005) ;执行完函数,此时ebp-30h上就完成了结构体返回值的拷贝
00401081   add         esp,4  ;平衡堆栈
00401084   mov         ecx,dword ptr [eax]
00401086   mov         dword ptr [ebp-20h],ecx ;这里创建一个临时的结构体
00401089   mov         edx,dword ptr [eax+4] ; 位对位的copy
0040108C   mov         dword ptr [ebp-1Ch],edx
0040108F   mov         ecx,dword ptr [eax+8]
00401092   mov         dword ptr [ebp-18h],ecx
00401095   mov         edx,dword ptr [eax+0Ch]
00401098   mov         dword ptr [ebp-14h],edx
0040109B   mov         eax,dword ptr [ebp-20h]
0040109E   mov         dword ptr [ebp-10h],eax  ;赋值给test
004010A1   mov         ecx,dword ptr [ebp-1Ch]
004010A4   mov         dword ptr [ebp-0Ch],ecx
004010A7   mov         edx,dword ptr [ebp-18h]
004010AA   mov         dword ptr [ebp-8],edx
004010AD   mov         eax,dword ptr [ebp-14h]
004010B0   mov         dword ptr [ebp-4],eax

call        @ILT+0(RerStruct)

20:       tagTest testRet;
21:       testRet.m_One = 1;
0040D7C8   mov         dword ptr [ebp-10h],1
22:       testRet.m_Two = 2;
0040D7CF   mov         dword ptr [ebp-0Ch],2
23:       testRet.m_Three = 3;
0040D7D6   mov         dword ptr [ebp-8],3
24:       testRet.m_Four = 4;
0040D7DD   mov         dword ptr [ebp-4],4
25:       return testRet;
0040D7E4   mov         eax,dword ptr [ebp+8] ; 取出前面压入栈的eax
0040D7E7   mov         ecx,dword ptr [ebp-10h] ;位对位的copy
0040D7EA   mov         dword ptr [eax],ecx
0040D7EC   mov         edx,dword ptr [ebp-0Ch]
0040D7EF   mov         dword ptr [eax+4],edx
0040D7F2   mov         ecx,dword ptr [ebp-8]
0040D7F5   mov         dword ptr [eax+8],ecx
0040D7F8   mov         edx,dword ptr [ebp-4]
0040D7FB   mov         dword ptr [eax+0Ch],edx
0040D7FE   mov         eax,dword ptr [ebp+8]

这里有个疑问,为什么还要多创建一个临时的结构体?

此时栈中有3个结构体 ebp-30  ebp-20  ebp-10

0012FF50  01 00 00 00  ....
0012FF54  02 00 00 00  ....
0012FF58  03 00 00 00  ....
0012FF5C  04 00 00 00  ....
0012FF60  01 00 00 00  ....
0012FF64  02 00 00 00  ....
0012FF68  03 00 00 00  ....
0012FF6C  04 00 00 00  ....
0012FF70  01 00 00 00  ....
0012FF74  02 00 00 00  ....
0012FF78  03 00 00 00  ....
0012FF7C  04 00 00 00 

学习,积累中......