AI智能
改变未来

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


写在前面

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

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

前篇答疑解惑

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

函数

  一个程序必须有一个函数,比如C语言中的

main函数

,也可以实现别的函数实现功能。本篇文章将从汇编的角度介绍函数,本次实验的代码十分简单。为了防止干扰,请在项目属性中关闭

增量链接

支持仅我的代码调试

(具体作用请搜索科普,它们会生成一些汇编代码来实现相应的功能)。

int main(){int a = 5;return 0;}

  得到的反汇编如下:

  通过汇编可以看出,函数生成的汇编采用

ebp寻址

的方式。前三句汇编进行用

ebp寻址的准备

提栈准备缓冲区

的操作,提供的缓冲区用来给函数内的局部变量用的。

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

push ebpmov ebp,espsub esp,0x40push ebxpush esipush edilea edi,[ebp-0x40]mov ecx,0x10mov eax,0xccccccccrep stosdmov dword ptr [ebp-8],5xor eax,eaxpop edipop esipop ebxmov esp,ebppop ebpret

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

lea edi,[ebp-0x40]mov ecx,0x10mov eax,0xccccccccrep stosd

  上面的代码是将

0xCC

填充满整个缓冲区,可帮助检测到堆栈缓冲区溢出,这是一种常见的攻击,威胁程序的安全性。

0xCC

即为我们调试的普通断点,汇编为

int 3

,即

VS

按下

F9

下断点(代码行左边的小红点)。

函数调用

int test(int a, int b){return a + b;}int main(){int a = test(1, 2);return 0;}

  然后看一下反汇编:

  可以看出函数调用时会通过

push

传递参数,然后

call

一个地址跳转到

test函数

,通过

eax

作为

返回值

。调用完毕后用

add esp,8

平栈,这个所谓的一种

调用约定

,被称为

__cdecl

。当然调用约定不知这一种,你也可以自定义,不过得从汇编上实现。

调用约定

  当一个函数被调用时,函数的参数会被传递给被调用的函数和返回值会被返回给调用函数。函数的调用约定就是描述参数是怎么传递和返回值,由谁平衡堆栈,这就是所谓的调用约定。  我们先给出常见的调用约定,其他的调用约定自行科普:

调用约定 __stdcall __cdecl __fastcall __pascal
参数传递顺序 从右到左 从左到右 从右到左 使用寄存器和栈
平栈 调用者 子程序 子程序 子程序

  当然,在

IDA

中你可能会看到其他调用约定,比如

__thiscall

等。由于调用约定并不是我想重点讲述的,具体细节自行科普。C语言默认的调用约定为

__cdecl

,所以在 函数调用 部分已有示例。这部分就用

__fastcall

做个为

调用约定

示例。

int __fastcall test(int a, int b){return a + b;}int main(){int a = test(1, 2);return 0;}

  如下是反汇编:

下一篇

  (七)羽夏看C语言——模板(C++)

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » (六)羽夏看C语言——函数