首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C语言汇编角度剖析函数调用的整个过程

提示:本文意在使用汇编语言给大家介绍函数调用中栈区上的过程变化,加深我们对于代码底层的理解,由于不同的编译器使用下,可能造成一些差异,但这并不影响我们对于知识原理的掌握,所以本文不必过多纠结细节处的变化...invoke_main() { return main(__argc, __argv, _get_initial_narrow_environment()); } 2.下面的代码分别是C语言代码和汇编语言代码...= 0; c = Add(a, b); printf("%d", c); return 0; } int main() main函数内部的汇编代码 { 004018B0...,会先对变量b进行压栈操作,然后在对变量a进行压栈操作 下面就是执行call指令后的画面,再次逐语句调试后就来到了Add函数内部的汇编语言代码 2.4 Add函数栈帧的创建和初始化 00E11770...我们会通过汇编语言中的call指令,先将其下一条指令的IP压栈到我们的栈帧空间当中,并且指向call指令,会进入到被调用函数汇编代码当中,进行被调用函数汇编指令 并且我们函数调用结束后,通过ret指令能够回到上一层函数

99910
您找到你想要的搜索结果了吗?
是的
没有找到

一个操作系统_09 C语言汇编语言

函数调用约定 编译器一般使用堆栈实现函数调用,每个进程都有自己的栈,用栈来传递参数,会带来以下问题: 参数存储在栈中,那么谁来负责回收参数所占的栈空间,是调用者?...还是被调用者 当参数很多的时候后,主调函数将参数以什么样的顺序传递 高级语言有调用的约定: ?...push 3 call sub 被调: push ebp mov ebp,esp mov eax,[ebp+8] sub eax,[ebp+12] pop ebp // 恢复 ebp C...& ASM 混合 C汇编混合编程有两种方式: 用汇编C单独单独编译,然后链接在一起 C代码嵌入汇编 C代码嵌入汇编: char* str = "C & ASM Code\n"; int count...内联汇编及其扩展 上面的例子是内联汇编的一个例子,基本的内敛汇编功能比较薄弱,在此基础上,GCC添加了扩展功能,在C语言里面用扩展汇编真的不舒服,相当于多了一种语言,需要依据其规则。

94420

操作系统只能用汇编C 语言吗?

因为目前所有的语言的开发环境里,C语言能做到编译成不依赖操作系统的形式二进制代码,C语言的各种脱离系统的库最丰富,最完整,C语言用来开发操作系统的工具最多。...举个例子:如果内核中希望使用printf这个函数,那么内核就必须自己实现printf,而不是依赖标准库,因为标准库是要依赖操作系统来完成真正的printf操作。...商用操作系统用C语言开发是因为工具齐全开发成本低,仅此而已。 JNode[2],一个用Java的操作系统。 这个世界上有很多闲人,他们一直在做着各种稀奇古怪的事情,就包括用各种语言开发操作系统。...最后我再补充一下:一个语言的第一个版本肯定是用别的语言的,但以后的版本就不一定了。这像是一个先有鸡还是先有蛋的问题,但实际不是。...举个例子吧:C语言的最早的编译器肯定不是C的,但用最早的编译器环境里的C语言是可以做出更复杂的编译器的,更复杂的编译器再做出支持更复杂语法的C,不停的迭代就可以了。

1.4K20

5.11 汇编语言:仿IF条件语句

通过运用标签与跳转即可构建不同的条件语句,本章将以C语言中条件语句为基础,并使用汇编语言介绍如何实现它们,以让读者能更加深入的理解C语言汇编语言之间的差异,帮助读者更好的理解并运用汇编语言。...在C语言中,AND运算符使用&&表示。...,应注意判断的转换,如果高级语言中是大于等于,那么低级语言则可转换为不大于则跳转,如果是小于等于,则对应的汇编语句则可直接转换为不小于则跳转,最后and语句必须三者全部一致,所以判断条件只需要顺序向下即可...双重IF嵌套语句其本质就是连续作比较,在仿汇编指令时应该由外到内逐层解析,这样才能写出条例清晰的汇编指令。...1 : 0)) { printf("xor eax,eax"); } return 0;}在仿这段C代码的汇编版时,我们首先要注意他是一个AND比较操作,两侧必须同时为1才可,因为这个特性的存在

17530

5.13 汇编语言:仿For循环语句

[start_count],ecx jmp L1 lop_end: int 3 invoke ExitProcess,0 main ENDPEND main11.20 仿For...10; x++) { if (Array[x] >= 50) { printf("out -> %d \n", Array[x]); } } return 0;}上述C语言代码如果通过汇编语言实现可以写成如下样子...代码中使用printf函数输出求得的四个值(max、min、sum、avg),并使用system函数暂停程序以便观察输出结果。...avg = %d \n", max_result,min_result,sum_result,avg_result); system("pause"); return 0;}上述代码读者可尝试使用汇编语言来实现一下...", y, x, result); } printf("\n"); } system("pause"); return 0;}乘法口诀表的实现方法只需要嵌套两层FOR循环语句,在使用汇编语言实现之前我们可以先来构建出这个双层循环体

16530

5.11 汇编语言:仿IF条件语句

通过运用标签与跳转即可构建不同的条件语句,本章将以C语言中条件语句为基础,并使用汇编语言介绍如何实现它们,以让读者能更加深入的理解C语言汇编语言之间的差异,帮助读者更好的理解并运用汇编语言。...在C语言中,AND运算符使用&&表示。...,应注意判断的转换,如果高级语言中是大于等于,那么低级语言则可转换为不大于则跳转,如果是小于等于,则对应的汇编语句则可直接转换为不小于则跳转,最后and语句必须三者全部一致,所以判断条件只需要顺序向下即可...双重IF嵌套语句其本质就是连续作比较,在仿汇编指令时应该由外到内逐层解析,这样才能写出条例清晰的汇编指令。...1 : 0)) { printf("xor eax,eax"); } return 0; } 在仿这段C代码的汇编版时,我们首先要注意他是一个AND比较操作,两侧必须同时为1才可,

35330

5.5 汇编语言函数调用约定

函数是任何一门高级语言中必须要存在的,使用函数式编程可以让程序可读性更高,充分发挥了模块化设计思想的精髓,今天我将带大家一起来探索函数的实现机理,探索编译器到底是如何对函数这个关键字进行实现的,并使用汇编语言模拟实现函数编程中的参数传递调用规范等...CDECL:C/C++默认的调用约定,调用方平栈,不定参数的函数可以使用,参数通过堆栈传递. STDCALL:被调方平栈,不定参数的函数无法使用,参数默认全部通过堆栈传递....首先先来写一段非函数版的堆栈使用案例,案例中模拟了编译器如何生成Main函数栈帧以及如何对栈帧初始化和使用的流程,笔者通过自己的理解写出了Debug版本的一段仿代码。...使用汇编仿数组传递方式,在main函数内我们动态开辟一块栈空间,并将数组元素依次排列在栈内,参数传递时通过lea eax,dword ptr [ ebp - 18h ]获取到数组栈地址空间,由于main...int) = ShowPrint; int Ret = pShowPrint(2, 4); printf("返回值 = %d \n", Ret); return 0; } 首先我们使用汇编仿

22120

5.12 汇编语言:仿While循环语句

loop指令,专门用来实现循环计数功能,由于是汇编指令,所以此loop语句必须读入ECX寄存器内的次数作为循环终止条件,每次读入会自动递减,具体汇编代码如下。...三层循环体这段C++代码实现了一个三重循环,用于生成所有由1到4中不重复的三个数字组成的序列。...While循环,其构建为汇编代码时稍有些难度,我们首先把外层框架构建好,先来构建一个二层While循环结构,如下汇编代码中,我们通过变量x DWORD控制外层循环次数,内层循环次数则使用y DWORD变量来控制...实现二分法该C++代码实现了一个二分查找算法,用于在已排序的数组中查找指定值的位置。...代码中定义了一个BinSearch函数,通过对传入数组进行二分查找,最终返回要查找的值在数组中的索引值。main函数调用了BinSearch函数,在已知数组中查找指定值并输出其在数组中的索引。

23530

5.12 汇编语言:仿While循环语句

loop指令,专门用来实现循环计数功能,由于是汇编指令,所以此loop语句必须读入ECX寄存器内的次数作为循环终止条件,每次读入会自动递减,具体汇编代码如下。...三层循环体 这段C++代码实现了一个三重循环,用于生成所有由1到4中不重复的三个数字组成的序列。...While循环,其构建为汇编代码时稍有些难度,我们首先把外层框架构建好,先来构建一个二层While循环结构,如下汇编代码中,我们通过变量x DWORD控制外层循环次数,内层循环次数则使用y DWORD变量来控制...实现二分法 该C++代码实现了一个二分查找算法,用于在已排序的数组中查找指定值的位置。...代码中定义了一个BinSearch函数,通过对传入数组进行二分查找,最终返回要查找的值在数组中的索引值。main函数调用了BinSearch函数,在已知数组中查找指定值并输出其在数组中的索引。

19020

5.5 汇编语言函数调用约定

函数是任何一门高级语言中必须要存在的,使用函数式编程可以让程序可读性更高,充分发挥了模块化设计思想的精髓,今天我将带大家一起来探索函数的实现机理,探索编译器到底是如何对函数这个关键字进行实现的,并使用汇编语言模拟实现函数编程中的参数传递调用规范等...,笔者通过自己的理解写出了Debug版本的一段仿代码。...使用汇编仿数组传递方式,在main函数内我们动态开辟一块栈空间,并将数组元素依次排列在栈内,参数传递时通过lea eax,dword ptr [ ebp - 18h ]获取到数组栈地址空间,由于main...)(int, int) = ShowPrint; int Ret = pShowPrint(2, 4); printf("返回值 = %d \n", Ret); return 0;}首先我们使用汇编仿...ShowPrint函数以及该函数所对应的int(__stdcall *pShowPrint)(int, int)函数指针,看一下在汇编层面该如何实现这个功能。

22820

C语言的main函数到底该怎么

前言 main函数是程序执行自定义的第一个函数。从开始学习C语言到现在,我们似乎看到了很多个版本的main函数,那么哪一种才是正确的呢?我们先来看看目前有哪些版本。...main函数版本 第一种,没有返回值,没有入参: main() 在C89标准中,这种写法是可以接受的,但使用现在的编译器编译时,会报告警,并且会将其返回值默认为int。...真相大白 C89/C99/C11标准文档中只提供了两种main函数的写法: int main(void) { /* ... */ } int main(int argc, char *argv[])...总结 至此,我们已经知道了c语言main函数的写法,我们来总结一下前面的内容: C标准只提供了两种main的形式,即前面提到的第三种和第五种。 为了代码的通用可移植性,建议采用标准提供的形式。...如果一个函数确定无需传入任何参数,那么用void限定是一个不错的选择。 函数没有声明返回值时,编译器默认其返回值为int。

1.4K20

手动编写C函数汇编代码

稍微解释一下其中的一些含义 目标文件和可执行文件都是由机器语言指令组成的 目标文件只包含你的代码所翻译的机器语言代码 可执行文件还包含你的代码中使用的库函数和启动代码的机器语言代码(启动代码充当着程序和操作系统之间的接口...) 编译器到底生成了什么 多说无益,这里用一个空白的C语言函数来看看编译器生成了哪些东西。...手动编写 这里就需要引入裸函数的概念了,裸函数就是编译器不帮你生成一行代码,所有的代码都必须你自己去手动编写 void __declspec(naked) Function(){ } 在正常情况下,我们一个空函数是不会出现报错的情况的...,但是裸函数则不然,直接用上面的方式,会跳到一个程序不认识的地方,如果对上一篇文章的堆栈图足够了解,就会知道造成这个情况的原因是什么。...这是因为函数汇编语言中是通过call来调用的,这个操作包含了两个步骤,一步是把下一条指令的地址push到堆栈中,一步是跳转到函数所要执行的地址,如果是一个空函数,它会再跳回到call指令的下一条地址,

97220

用纯汇编来写strlen一定比C语言的快吗?

事情是这样的,我在操作系统,看到田宇大佬的代码里面,strlen也是用汇编来写的,我很不解,这个不是可以用C来实现吗?难不成纯汇编更快?于是我就写了一个小程序来做实验。看看这两者的速度。...这个程序首先是随机生成了1E6长度的字符串,然后分别进行1000次计算大小,可以发现,C语言函数运行的更快一些些。...total_c += clock()-start; } printf("%lf\n", 1.0*total_c/times); } 运行速度: 田宇大佬的汇编版本:平均517.047000ms...C语言版本:平均430.027000ms 可以看到C版本的运行的更快,快了16.8%。...考虑到可能是这两个函数执行先后性的影响,交换一下他们的先后顺序,得到的结果依然不变。 怀着疑问,再来看看他们编译后的汇编代码:也许jmp指令对于处理器的分支预测更友好?

55510
领券