您的位置:首页 > 编程语言 > C语言/C++

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

2021-09-07 16:21 806 查看

写在前面

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

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

前篇答疑解惑

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

函数

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

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

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

  得到的反汇编如下:

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

ebp寻址
的方式。前三句汇编进行用
ebp寻址的准备
提栈准备缓冲区
的操作,提供的缓冲区用来给函数内的局部变量用的。

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

push ebp
mov ebp,esp
sub esp,0x40
push ebx
push esi
push edi
lea edi,[ebp-0x40]
mov ecx,0x10
mov eax,0xcccccccc
rep stosd
mov dword ptr [ebp-8],5
xor eax,eax

pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret

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

lea edi,[ebp-0x40]
mov ecx,0x10
mov eax,0xcccccccc
rep 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++)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: