从汇编层面聊一聊函数到底是什么,怎么实现的
此系列是本人一个字一个字码出来的,包括示例和实验截图。本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。
你如果是从中间插过来看的,请仔细阅读 (一)羽夏看C语言——简述 ,方便学习本教程。
答案:不会。
解答:我相信亲手做实验的人都会知道的。
一个程序必须有一个函数,比如C语言中的<code>main函数</code>,也可以实现别的函数实现功能。本篇文章将从汇编的角度介绍函数,本次实验的代码十分简单。为了防止干扰,请在项目属性中关闭<code>增量链接</code>和<code>支持仅我的代码调试</code>(具体作用请搜索科普,它们会生成一些汇编代码来实现相应的功能)。
得到的反汇编如下:

通过汇编可以看出,函数生成的汇编采用<code>ebp寻址</code>的方式。前三句汇编进行用<code>ebp寻址的准备</code>和<code>提栈准备缓冲区</code>的操作,提供的缓冲区用来给函数内的局部变量用的。
有些生成的反汇编可能是这样的版本:
有些人可能看不懂以下代码:
上面的代码是将<code>0xCC</code>填充满整个缓冲区,可帮助检测到堆栈缓冲区溢出,这是一种常见的攻击,威胁程序的安全性。<code>0xCC</code>即为我们调试的普通断点,汇编为<code>int 3</code>,即<code>VS</code>按下<code>F9</code>下断点(代码行左边的小红点)。
然后看一下反汇编:
可以看出函数调用时会通过<code>push</code>传递参数,然后<code>call</code>一个地址跳转到<code>test函数</code>,通过<code>eax</code>作为<code>返回值</code>。调用完毕后用<code>add esp,8</code>平栈,这个所谓的一种<code>调用约定</code>,被称为<code>__cdecl</code>。当然调用约定不知这一种,你也可以自定义,不过得从汇编上实现。
当一个函数被调用时,函数的参数会被传递给被调用的函数和返回值会被返回给调用函数。函数的调用约定就是描述参数是怎么传递和返回值,由谁平衡堆栈,这就是所谓的调用约定。
我们先给出常见的调用约定,其他的调用约定自行科普:
调用约定
__stdcall
__cdecl
__fastcall
__pascal
参数传递顺序
从右到左
从左到右
使用寄存器和栈
平栈
调用者
子程序
当然,在<code>IDA</code>中你可能会看到其他调用约定,比如<code>__thiscall</code>等。由于调用约定并不是我想重点讲述的,具体细节自行科普。C语言默认的调用约定为<code>__cdecl</code>,所以在 函数调用 部分已有示例。这部分就用<code>__fastcall</code>做个为<code>调用约定</code>示例。
如下是反汇编:
(七)羽夏看C语言——模板(C++)
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
本文来自博客园,作者:寂静的羽夏 ,一个热爱计算机技术的菜鸟
转载请注明原文链接:https://www.cnblogs.com/wingsummer/p/15230787.html