天天看点

(六)羽夏看C语言——函数

从汇编层面聊一聊函数到底是什么,怎么实现的

  此系列是本人一个字一个字码出来的,包括示例和实验截图。本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。

你如果是从中间插过来看的,请仔细阅读 (一)羽夏看C语言——简述 ,方便学习本教程。

  答案:不会。

  解答:我相信亲手做实验的人都会知道的。

  一个程序必须有一个函数,比如C语言中的<code>main函数</code>,也可以实现别的函数实现功能。本篇文章将从汇编的角度介绍函数,本次实验的代码十分简单。为了防止干扰,请在项目属性中关闭<code>增量链接</code>和<code>支持仅我的代码调试</code>(具体作用请搜索科普,它们会生成一些汇编代码来实现相应的功能)。

  得到的反汇编如下:

(六)羽夏看C语言——函数

  通过汇编可以看出,函数生成的汇编采用<code>ebp寻址</code>的方式。前三句汇编进行用<code>ebp寻址的准备</code>和<code>提栈准备缓冲区</code>的操作,提供的缓冲区用来给函数内的局部变量用的。

  有些生成的反汇编可能是这样的版本:

  有些人可能看不懂以下代码:

  上面的代码是将<code>0xCC</code>填充满整个缓冲区,可帮助检测到堆栈缓冲区溢出,这是一种常见的攻击,威胁程序的安全性。<code>0xCC</code>即为我们调试的普通断点,汇编为<code>int 3</code>,即<code>VS</code>按下<code>F9</code>下断点(代码行左边的小红点)。

  然后看一下反汇编:

(六)羽夏看C语言——函数
(六)羽夏看C语言——函数

  可以看出函数调用时会通过<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语言——模板(C++)

(六)羽夏看C语言——函数
(六)羽夏看C语言——函数

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可

本文来自博客园,作者:寂静的羽夏 ,一个热爱计算机技术的菜鸟

转载请注明原文链接:https://www.cnblogs.com/wingsummer/p/15230787.html

(六)羽夏看C语言——函数

继续阅读