39 :C语言与汇编语言混合编程

目录

编译过程

编译小知识

C语言中函数是如何进行调用的?

寄存器压栈过程

C语言函数调用过程

函数调用过程

函数返回过程

C语言中的调用约定

gcc编译器使用的栈帧布局

ebp是函数调用以及函数返回的核心寄存器 

用汇编语言编写Linux应用程序

交互关键字

汇编和C混合编程注意事项

小结

思考


编译过程

39 :C语言与汇编语言混合编程_第1张图片

编译小知识

39 :C语言与汇编语言混合编程_第2张图片

C语言中函数是如何进行调用的?

39 :C语言与汇编语言混合编程_第3张图片

寄存器压栈过程

39 :C语言与汇编语言混合编程_第4张图片

调用函数 func 会将函数的 返回地址 压入到栈中。此时,esp栈指针寄存器 会往下移动。

39 :C语言与汇编语言混合编程_第5张图片

当程序执行 ret 的时候,程序恢复到 原来 调用 call的位置。在汇编代码层面,call 做的事情 和 ret做的事情,正好相反。

39 :C语言与汇编语言混合编程_第6张图片

C语言函数调用过程

函数调用过程

39 :C语言与汇编语言混合编程_第7张图片

函数返回过程

39 :C语言与汇编语言混合编程_第8张图片

39 :C语言与汇编语言混合编程_第9张图片

C语言中的调用约定

39 :C语言与汇编语言混合编程_第10张图片

39 :C语言与汇编语言混合编程_第11张图片

gcc编译器使用的栈帧布局

39 :C语言与汇编语言混合编程_第12张图片

ebp是函数调用以及函数返回的核心寄存器 

39 :C语言与汇编语言混合编程_第13张图片

用汇编语言编写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:~$ 

交互关键字

  1. global : 从汇编语言中导出符号(变量或函数)
  2. extern : 使用外部文件中定义的符号(变量或函数)

实例分析:

39 :C语言与汇编语言混合编程_第14张图片

接着来看下一个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混合编程注意事项

  1. 相同的目标文件格式(如:elf格式)
  2. 相同的函数调用约定(如:cdecl调用约定)
  3. 相同的活动记录(栈帧)结构(如:ebp基准)

小结

39 :C语言与汇编语言混合编程_第15张图片

思考

可以把 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'

你可能感兴趣的:(#,汇编语言相关知识,#,汇编语言)