gcc 内嵌汇编的学习笔记 IV
来源:互联网 发布:知行网络 编辑:程序博客网 时间:2024/06/05 11:22
gcc 内嵌汇编的学习笔记 IV
--函数调用
作者:ShellEx.
ShellEx.cn && blog.csdn.net/shellex 版权所有
没有经验,还是通过反汇编出来的代码来学习。先写一个简单的函数
调用的C++ code Sample:
#include <stdio.h>
int Add(int a, int b) {
return a + b;
}
int main() {
int in1 = 0,in2 = 0, out =0 ;
printf("PLZ input 2 Number:(x1, x2) /n");
scanf("%d, %d", &in1, &in2);
out = Add(in1, in2);
printf("out = %d",out);
return 0;
}
///////////////////////////////////////////////////////////////
察看了得出的汇编代码,有几个发现:
i. 对于不同的编译方法(用纯C,C++)得出的函数名符号是不同的。这一
点大家早就知道了。因为这是很多C++编译器实现函数重载的基础。
对于g++,函数标示会变成形如"__Z3Addii"这样的东西。前缀不知道
是虾米东西,但是后缀是参数列表的参数类型名缩写。
ii. 编译器会在汇编代码文件里面加入新标示用于标示函数:
.globl _Add
.def _Add; .scl 2; .type 32; .endef
_Add:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
addl 8(%ebp), %eax
popl %ebp
ret
如果函数是static的那么就是这样:
.def _Add; .scl 3; .type 32; .endef
_Add:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
addl 8(%ebp), %eax
popl %ebp
ret
接着我看看调用函数Add的汇编代码:
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl -4(%ebp), %eax
movl %eax, (%esp)
call _Add
movl %eax, -12(%ebp)
没有传说中的压栈操作。但是效果是一样的。因为%esp保存着栈顶指针。
相当于:
movl -8(%ebp), %eax
push %eax
movl -4(%ebp), %eax
push %eax
call _Add
movl %eax, -12(%ebp)
从右往左依次把参数压栈。call _Add后,可以看到结果被放在eax里面。
我记得VC好像就用push的多,而gcc则总是默认用mov。(Borland好像也
喜欢用mov),记不清了。
接着写一段汇编调用C函数的代码:
#include <stdio.h>
int Add(int a, int b) {
return a + b;
}
int main() {
int in1 = 0,in2 = 0, out =0 ;
printf("PLZ input 2 Number:(x1, x2) /n");
scanf("%d, %d", &in1, &in2);
int (*pf)(int,int) = Add;
asm volatile(
"nop #FunTest /n/t"
"mov %3, 4(%%esp) /n/t"
"mov %2, (%%esp) /n/t"
"call *%0 /n/t"
"mov %%eax, %1 /n/t"
:"+r"(pf),"+r"(out)
:"r"(in1),"r"(in2)
:"esp","eax"
);
//OllyDbg
printf("out = %d/n",out);
return 0;
}
///////////////////////////////////////////////////////////////
在 AT&T 汇编格式中,绝对转移和调用指令(jump/call)的操作数前要
加上*作为前缀,所以我在%0前加了*。而intel汇编是不需要的。在调用
函数时,我用了函数指针,因为直接用函数名会报错。当然,其实这样
写也可以:
asm volatile(
"nop #FunTest /n/t"
"mov %2, 4(%%esp) /n/t"
"mov %1, (%%esp) /n/t"
"call _Add /n/t"
"mov %%eax, %0 /n/t"
:"+r"(out)
:"r"(in1),"r"(in2)
:"esp","eax"
);
但是这样写的前提是你知道生成的函数标识是什么才行。。。
PS:发现一点小问题,有时在gcc 中生成不了的内嵌汇编代码模板在g++
里面可以通过,直到用as编译时才会报错,原因不明。比如说如果在调
用函数时不用函数指针pf而用直接用函数名Add倒入汇编模板,就会出现
这样的问题。
ShellEx.cn && blog.csdn.net/shellex 版权所有
- gcc 内嵌汇编的学习笔记 IV
- gcc 内嵌汇编的学习笔记 I
- gcc 内嵌汇编的学习笔记 II
- gcc 内嵌汇编的学习笔记 III
- 80386汇编+GCC的内嵌汇编
- 80386汇编+GCC的内嵌汇编
- gcc内嵌汇编
- GCC内嵌汇编
- GCC内嵌汇编
- GCC内嵌汇编
- GCC内嵌汇编
- gcc内嵌汇编
- GCC内嵌汇编
- GCC内嵌汇编
- gcc 内嵌汇编
- GCC 内嵌汇编
- GCC内嵌汇编
- GCC内嵌汇编
- jbpm+tomcat+mysql配置指南
- gcc 内嵌汇编的学习笔记 II
- 网站后台的流程
- SQL Server 2005 考试(包括答案)
- gcc 内嵌汇编的学习笔记 III
- gcc 内嵌汇编的学习笔记 IV
- java包装类
- SQL Server 作业
- 扩展你的WIndows标准控件
- 面向对象技术伪术语--主动对象的批判 续
- “技术工作”感悟
- c++ primer第一章习题
- 使用debootstrap做一个属于自己的系统
- 广岛原子弹爆炸实况