目录
编译过程
编译小知识
C语言中函数是如何进行调用的?
寄存器压栈过程
C语言函数调用过程
函数调用过程
函数返回过程
C语言中的调用约定
gcc编译器使用的栈帧布局
ebp是函数调用以及函数返回的核心寄存器
用汇编语言编写Linux应用程序
交互关键字
汇编和C混合编程注意事项
小结
思考
编译过程
编译小知识
C语言中函数是如何进行调用的?
寄存器压栈过程
调用函数 func 会将函数的 返回地址 压入到栈中。此时,esp栈指针寄存器 会往下移动。
当程序执行 ret 的时候,程序恢复到 原来 调用 call的位置。在汇编代码层面,call 做的事情 和 ret做的事情,正好相反。
C语言函数调用过程
函数调用过程
函数返回过程
C语言中的调用约定
gcc编译器使用的栈帧布局
ebp是函数调用以及函数返回的核心寄存器
用汇编语言编写Linux应用程序
global _start
[section .data]
vstr db "D.T.Software",0X0A
[section .text]
_start:
mov edx,13
mov ecx,vstr
mov ebx,1
mov eax,4
int 0x80
mov ebx,0
mov eax,1
int 0x80
编译链接,运行如下所示:
delphi@delphi-vm:~$ nasm -f elf entry.asm -o entry.o
delphi@delphi-vm:~$ ld -s entry.o -o app.out
delphi@delphi-vm:~$ ./app.out
D.T.Software
delphi@delphi-vm:~$
交互关键字
- global : 从汇编语言中导出符号(变量或函数)
- extern : 使用外部文件中定义的符号(变量或函数)
实例分析:
接着来看下一个demo:
entry.asm
global _start
global vstr
global vlen
global print
extern c_func;
[section .data]
vstr db "D.T.Software",0X0A
vlen dd $ - vstr
[section .text]
_start:
mov ebp,0
call c_func
call exit
print:
push ebp
mov ebp,esp
mov edx,[ebp + 12]
mov ecx,[ebp + 8]
mov ebx,1
mov eax,4
int 0x80
pop ebp
ret
exit:
mov ebx,0
mov eax,1
int 0x80
main.c
extern void print(char*,int len);
extern char vstr[];
extern int vlen;
int c_func()
{
print(vstr,vlen);
return 0;
}
编译,链接,运行:
delphi@delphi-vm:~$ nasm -f elf entry.asm -o entry.o
delphi@delphi-vm:~$ gcc -c main.c -o main.o
delphi@delphi-vm:~$ ld -s entry.o main.o -o app.out
delphi@delphi-vm:~$ ./app.out
D.T.Software
delphi@delphi-vm:~$
接下来,将 main.c 改成如下的程序:
extern void print(char*,int len);
extern char vstr[];
extern int vlen;
int c_func()
{
char* delphi = "Delphi\n";
//print(vstr,vlen);
print(delphi,7);
return 0;
}
现在只需要编译 c文件,然后链接,运行就行:
delphi@delphi-vm:~$ gcc -c main.c -o main.o
delphi@delphi-vm:~$ ld -s entry.o main.o -o app.out
delphi@delphi-vm:~$ ./app.out
Delphi
delphi@delphi-vm:~$
汇编和C混合编程注意事项
- 相同的目标文件格式(如:elf格式)
- 相同的函数调用约定(如:cdecl调用约定)
- 相同的活动记录(栈帧)结构(如:ebp基准)
小结
思考
可以把 main.c 文件中的 c_func 函数名字,改为 main函数名吗?
当然不行,编译可以编译通过,但是会链接出错。
delphi@delphi-vm:~$ nasm -f elf entry.asm -o entry.o
delphi@delphi-vm:~$ gcc -c main.c -o main.o
delphi@delphi-vm:~$ ld -s entry.o main.o -o app.out
entry.o: In function `_start':
entry.asm:(.text+0x6): undefined reference to `c_func'