目录
编译过程
编译小知识
C语言中函数是如何进行调用的?
寄存器压栈过程
C语言函数调用过程
函数调用过程
函数返回过程
C语言中的调用约定
gcc编译器使用的栈帧布局
ebp是函数调用以及函数返回的核心寄存器
用汇编语言编写Linux应用程序
交互关键字
汇编和C混合编程注意事项
小结
思考
调用函数 func 会将函数的 返回地址 压入到栈中。此时,esp栈指针寄存器 会往下移动。
当程序执行 ret 的时候,程序恢复到 原来 调用 call的位置。在汇编代码层面,call 做的事情 和 ret做的事情,正好相反。
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:~$
实例分析:
接着来看下一个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:~$
可以把 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'