C语言中的函数(或称为方法或者过程)是通过进程的栈空间来进行管理的,一个个函数在栈空间的表现就像是一幅一幅的图片,称为栈帧(stack frame)。其中寄存器%ebp始终指向栈帧的开始,而寄存器%esp则像游标一样在相邻两个栈帧中滑动来存取值。
下面以一个实际例子来说明:
由上图可知函数compare调用函数max, 不同颜色代表不同的栈帧,我们来开始分析汇编代码:
首先我们假设此时esp寄存器为某个值Vbase(上图中第二个箭头指向的位置);
pushl %ebp ;将%ebp寄存器的值入栈,此时Vesp = Vbase - 4;
movl %esp, %ebp; 将%esp的值赋值给%ebp,则Vebp = Vbase -4;
subl $8, %esp; 将%esp的值减去8,即分配栈空间,用于保存临时变量,这里是x和y,
;此时Vesp = Vbase-4-8 = Vbase - 12
movl $7, 4(%esp); 这里将y的值7存到Vesp+4指定的地址
movl $5, %esp;这里将x的值5存储到Vesp指定的地址
call max;这里调用max函数,call指令会首先将函数执行完后的返回地址(即call后面第一条指令的虚拟地址)压入栈
;中,此时Vesp = Vbase - 16
//*************************************这里进入max函数********************************************************//
pushl %ebp;将%ebp寄存器的值入栈,此时Vesp = Vbase - 20;
movl %esp, %ebp; 将%esp的值赋值给ebp,则Vebp = Vbase -20;
movl 12(%ebp), %eax;将Vbase - 8地址即y的值存到%eax寄存器中
cmpl %eax, 8(%ebp);将y 与Vbase - 12地址即x的值作比较
setg %al;如果x大于y设置%al为1,相反设置为0
movzbl %al, %eax;用零扩展位方式将al的值扩展到%eax中,即清除%eax的高24位
popl %ebp;将进入函数时的%ebp值出栈存入%ebp寄存器中,此时Vesp = Vbase -16,指向“返回地址”
ret;将Vesp指向的地址的值转入%eip寄存器,然后让%esp+4,即出栈,此时Vesp = Vbase -12,指向x
//*************************************这里退出max函数********************************************************//
testl %eax, %eax;这里比较max的返回值是不是为1,函数的返回值一般存在eax寄存器中
mov $35, %edx; 这里编译器将x*y直接优化成35,将该值存到%edx寄存器中
cmovne %edx, %eax;这里用到了tesl的值,如果返回值为1,则将%edx的值赋值到%eax中
leave;将%ebp的值(即compare函数第二个语句中的%ebp值)赋值给%esp,即回收分配给x和y的空间,
;然后将%esp指向的栈顶地址中的值赋值给%ebp
ret;将Vesp指向的地址的值转入%eip寄存器,然后让Vesp+4,即出栈,此时Vesp = Vbase
扩展知识:由于芯片中寄存器是被所有方法共有的,为了不让被调用者破坏调用者的数据,必须遵循下面的规则:
1.寄存器%eax,%edx和%ecx作为调用者保存寄存器,如果函数P调用函数Q,那么Q可以任意使用这些寄存器,不用
担心会损坏P的数据
2.寄存器%ebx,%esi和%edi为被调用者保存寄存器,如果函数P调用函数Q,如果Q需要用到这些寄存器的时候,必须先
保存,当函数退出时恢复该寄存器的值。
相关推荐
汇编语言实现对引脚底层的配置,使用C语言调用汇编语言函数进行点灯.zip汇编语言实现对引脚底层的配置,使用C语言调用汇编语言函数进行点灯.zip汇编语言实现对引脚底层的配置,使用C语言调用汇编语言函数进行点灯....
2. 增强安全性:汇编语言函数可以提供更高的安全性,因为汇编语言代码可以直接访问硬件资源,从而减少安全漏洞的可能性。 3. 提高灵活性:C语言函数调用汇编语言函数可以提供更高的灵活性,因为开发者可以根据需要...
3. **C语言函数声明**:在C代码中,需要声明汇编函数,指定其返回类型和参数类型。这样,C编译器才能正确地生成调用汇编函数所需的指令。 4. **寄存器管理**:8051有有限的几个工作寄存器,因此在C调用汇编时,需要...
综上所述,通过在KEIL C51环境中使用#pragma指令嵌入汇编代码、正确配置项目选项、添加并链接相应的库文件、编写和调用汇编函数以及了解C和汇编之间的参数传递方式和命名规则,可以在C语言中有效地使用汇编语言来...
标题 "12864(无字库) C语言汇编代码" 指的是一个针对12864液晶显示屏的编程项目,这个项目不依赖内置字库,而是使用C语言和汇编语言进行编写。12864液晶屏是一种常见的图形点阵液晶显示器,通常用于嵌入式系统或...
#### 三、示例代码分析 本节将对提供的示例代码进行详细解析,帮助理解其工作原理。 ##### 3.1 头文件`asm.h` ```c #ifdef ASM unsigned long shiftR1(register unsigned long); #else extern unsigned long ...
通过对上述C语言源代码的反汇编分析,我们不仅了解了函数调用的一般流程,还学习了如何在汇编级别上追踪函数调用的具体细节。这种能力对于理解和分析二进制程序至关重要,尤其是在安全领域中进行漏洞挖掘或恶意软件...
"pic18 双字节除法 C语言汇编混合编程"这个主题涉及了如何在PIC18系列单片机上,使用C语言调用汇编函数来实现一个高效的16/16位定点除法操作。以下是对这个主题的详细解释: 1. **PIC18单片机**:PIC18是Microchip ...
为了更好地理解上述理论,我们可以通过Visual C++ 6.0等工具对C语言程序进行反汇编分析。比如,编写一个简单的函数调用示例,使用反汇编工具查看其对应的汇编代码,从而深入了解函数调用的具体过程。 #### 五、总结...
- 汇编函数中,直接从寄存器A读取第一个参数,并从堆栈中读取其他参数。 #### 4. 变量和函数的接口问题 当C语言和汇编语言混合编程时,需要注意变量和函数的接口问题。 - **访问C变量**: - 在汇编程序中,C语言...
1. **定义接口**:在C语言中声明一个函数,这个函数的实现将在汇编代码中提供。函数声明包括参数类型和返回值类型,例如: ```c extern int add(int a, int b); ``` 2. **汇编子程序**:编写汇编代码,实现函数...
本文将详细探讨如何进行C语言与汇编语言的混合编程,包括C语言直接插入汇编代码、C文件调用无参数无返回值的汇编函数以及C文件调用有参数有指针返回值的汇编函数。 首先,让我们来看看C语言直接插入汇编语言的部分...
在Keil C51中,可以通过特定的方式将汇编代码嵌入到C语言程序中,或者在汇编代码中调用C语言函数。混合编程的主要好处是可以将关键部分用汇编语言编写以提高效率,而其他部分则使用C语言以保持代码的可读性和可维护...
它们能够处理C语言的基本语法,支持常见的预处理、编译、汇编和链接步骤,帮助开发者将源代码转化为可以在特定平台上运行的二进制程序。 其次,"常用函数查找工具"是C语言学习和开发中的另一个重要助手。这个工具...
- 分析简单的C代码并生成对应的汇编,观察其转换过程。 - 对比不同优化级别的汇编代码,理解编译器优化的影响。 - 实现简单的算法或功能,先用C编写,再查看汇编,加深理解。 6. **调试技巧**: - 使用GDB等...
使用汇编语言对C语言函数调用方法求平均数 在计算机编程中,汇编语言和C语言都是常用的编程语言。汇编语言是一种低级语言,它可以直接控制计算机硬件,具有高效、灵活和可靠的特点。但是,汇编语言的编程难度较高,...
2. 字符和字符串输出:C语言的函数可能包含写入单个字符和整行字符串到LCD的功能,而汇编代码可能用于优化字符刷新速度。 3. 图形操作:如果LCD支持图形显示,代码可能包含点画、线画、填充矩形等基本图形操作函数。...
此外,汇编代码中的指令应该用C语言的变量和函数进行合理的封装,以保持程序的整体性和可读性。 3. 内嵌汇编的实例:文档中提到的一些练习示例和参考答案可以作为学习内嵌汇编编程的工具。通过实际编写和调试这些...
现在,让我们分析给定的C语言中嵌入ASM汇编代码的例子: ```c void main() { int x = 1; int y = 7; _asm { mov ecx, x; add ecx, y; mov x, ecx; } printf("%d", x); scanf("%d", &y); } ``` 在这个...
在这个项目中,我们用C语言编写了一个简单的计算机模拟器,它能执行由汇编器产生的机器代码。通过模拟器,我们可以观察和分析程序的执行过程,理解计算机内部如何处理指令。"ssim"可能就是这个模拟器的源代码或者...