【C语言】函数栈帧的创建和销毁(四)

简介: 【C语言】函数栈帧的创建和销毁(四)

这两个ebp要注意,上一个ebp其实就是我们main函数的栈底。这个ebp弹出后除了栈顶指针要-4,我们的栈底指针ebp也会回到main函数的栈底

也就是说我们回到了main函数了。

通过使用"ret"指令,可以从栈中弹出之前存储的返回地址,将控制权返回给调用者。

"ret"指令用于从子程序或函数中返回到调用者,并将控制权返回到之前存储的返回地址。

回来了

然后就是这一条指令,我们之前故意留着。

为什么要esp要add一个8呢?

我们看

我们之前用ecx,eax来接收实参,现在我们还需要用吗?

当然不需要那么我们栈底还要它们干什么???

这里我们猜想,如果传三个值那么是不是要+12呢?当然我也不知道,我只是猜测而言,合理的猜测。

然后是这几条。

将eax赋给ebp-12。

这个eax和我们接收实参的eax是不同的,是我们专门用来存储返回值的eax

ebp-12就是我们的c

接下来看这几条

我们先看第一条,意思是讲c的值取出放到edx,这个寄存器在我们之前完全没有使用过。

然后还是压一个edx.

接下来,使用"push"指令将字符串常量的地址(offset string “%d\n”)推入栈中。这是为了准备将其作为参数传递给printf函数,这个字符串格式控制符将被用来打印先前提供的值

然后我们调用printf这个库函数。

在printf函数结束后,使用"add"指令将esp寄存器的值增加8个字节。这是为了清除栈上的参数,以便恢复栈的状态。

最后是xor

"xor"是一个汇编指令,用于执行两个操作数之间的异或运算。

"xor"指令可以用于执行寄存器之间的异或运算,也可以用于执行寄存器和内存之间的异或运算。

例如,"xor eax, ebx"将执行eax寄存器和ebx寄存器之间的异或运算,并将结果存储回eax寄存器中。

XOR操作在计算机科学和密码学中有多种应用。它可以用于数据加密、校验和计算、数据交换等场景,提供了一种简单而有效的数据处理和安全保护机制。可能是为了保护我们的最后的结果,我猜测

然后弹出edi,esi,ebx

最后只剩这么一点了。

cmp一下仅供了解:

仅供了解:

“cmp"指令的语法通常是"cmp operand1,

operand2”,其中operand1和operand2可以是寄存器、内存地址或立即数。

当执行"cmp"指令时,计算机会将operand1的值与operand2的值进行比较,并根据比较结果设置标志位。具体来说,"cmp"指令执行以下操作:

将operand1的值减去operand2的值,并更新标志位。这个减法操作不会修改operand1和operand2的值,只是用于比较它们的大小。

根据减法结果设置标志位。比较的结果可以分为三种情况:

如果operand1等于operand2,则零标志位(ZF)被设置为1。

如果operand1小于operand2,则符号标志位(SF)被设置为1。

如果operand1大于operand2,则无符号溢出标志位(CF)和符号溢出标志位(OF)被设置为1。

“cmp"指令通常与条件跳转指令(如"je”、“jne”、"jg"等)一起使用,用于根据比较结果执行不同的操作。

总之,"cmp"指令用于比较两个操作数的值,并根据比较结果设置标志位。这样可以在程序中根据比较结果来做出不同的决策,例如执行条件跳转或选择不同的执行路径。

"call __chkesp (00401160)"是一个汇编语言指令,它的作用是调用名为 “__chkesp” 的过程或函数。

在汇编语言中,“call” 指令用于调用一个过程或函数,它将指令流跳转到目标过程或函数的起始地址,并将当前指令的地址(即 call

指令的下一条指令地址)保存在堆栈上,以便在返回时回到正确的位置。

“__chkesp” 是一个函数或过程的名称,后面的 “(00401160)”

是函数的入口地址。入口地址是函数在内存中的位置,它唯一地标识了函数的起始地址。注意,这个地址是一个虚拟地址,并以十六进制表示。

因此,“call __chkesp (00401160)” 意味着执行一个函数或过程,该函数的名称为 “__chkesp”,其起始地址为

00401160。执行到这条指令时,程序流会跳转到函数的起始地址,并将当前指令的地址保存在堆栈上,以便在函数执行完毕后返回到正确的位置。

最后这三句我就不画了。后面的仅供了解了解,不必深究,我现在也没有这个能力。

总结🍊

***这篇博客我们系统的介绍了函数栈帧的创建和销毁。我们解决了这些问题。

  1. 局部变量是怎么创建的?
  2. 为什么局部变量的值是随机值?
  3. 函数是怎么传参的?
  4. 传参的顺序是怎么样的?
  5. 形参和实参是什么关系?
  6. 函数调用是怎么做的?
  7. 函数调用结束后是怎么返回的?

这篇博客写下来感觉我的C语言功法又进一步。虽然有点累但是真的很有成就感

最后如果这篇博客有帮助到你,欢迎点赞关注加收藏

如果本文有任何错误或者有疑点欢迎在评论区评论

目录
相关文章
|
7月前
|
存储 安全 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
|
7月前
|
存储 编译器 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
|
7月前
|
存储 编译器 程序员
C语言之反汇编查看函数栈帧的创建与销毁(一)
C语言之反汇编查看函数栈帧的创建与销毁(一)
C语言之反汇编查看函数栈帧的创建与销毁(一)
|
编译器 Linux C语言
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)(上)
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)
|
存储 C语言
打通你学习C语言的任督二脉-函数栈帧的创建和销毁(上)
打通你学习C语言的任督二脉-函数栈帧的创建和销毁(上)
65 0
|
存储 C语言
C语言-------函数栈帧的创建和销毁------剖析描骨
C语言-------函数栈帧的创建和销毁------剖析描骨
|
4月前
|
存储 C语言
【C语言】——函数栈帧的创建与销毁
【C语言】——函数栈帧的创建与销毁
|
7月前
|
存储 编译器 C语言
C语言:底层剖析——函数栈帧的创建和销毁
C语言:底层剖析——函数栈帧的创建和销毁
|
7月前
|
存储 编译器 程序员
C语言之反汇编查看函数栈帧的创建与销毁(二)
C语言之反汇编查看函数栈帧的创建与销毁(二)
|
编译器 C语言
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)(下)
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)