c语言与汇编语言混合编程

如何从汇编语言过渡到c语言?

从编译过程谈起

 编译小知识

源代码编译后得到目标文件 (二进制文件)

不同语言可编译得到相同格式的目标文件

链接器负责将目标文件组装得到可执行文件

老生常谈的问题。。。

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

栈上的秘密

cdecl 调用约定 (C语言默认调用约定)

参数从右向左入栈

函数调用者负责参数的入栈出栈

函数本身根据约定使用栈中参数

 gcc编译器使用的栈帧布局

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

ebp为当前栈帧的基准 (存储上一个栈帧的ebp值)

通过ebp能够获取返回值地址,参数,局部变量,等

目标文件分析


void g()
{
}

int func(int a, int b)
{
    g();
    a = a + b;
    return a;
}

int main()
{
    func(1, 2);
    return 0;
}

leave 指令将 ebp 寄存器的值赋给 esp 寄存器中,以释放分配给该过程的所有堆栈空间。然后,它从堆栈中恢复 ebp 寄存器的旧值。

通过反汇编我们观察到,c语言进行函数调用必须经历的4个步骤,将当前的ebp入栈;让ebp指向esp,也就是上一个栈帧的ebp值;函数执行完后,让esp指向ebp,将old ebp 出栈,ebp恢复为上一个栈帧的ebp值;最后返回到函数调用完后的下一条指令执行。

使用汇编语言编写Linux可执行程序

定义 _start 标签作为程序执行的起点

通过 int 0x80 使用内核服务 (执行系统调用)

交互关键字

global

  • 从汇编语言中导出符号 (变量或函数) 

extern

  • 使用外部文件中定义的符号 (变量或函数)

示例分析

混合编程注意事项

相同的目标文件格式 (如:elf 格式)

相同的函数调用约定 (如:cdecl 调用约定)

相同的活动记录 (栈帧) 结构 (如:ebp 基准)

混合编程实战

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()
{
    char* delphi = "Delphi\n";
    
    print(vstr, vlen);
    
    return 0;
}

成功打印了输出结果。

nasm -f elf entry.asm -o entry.o

gcc -c mian.c -o main.o

ld -s entry.o main.o -o app.out

通过上述方式生成可执行文件。

global关键字用来让一个符号对链接器可见,可以供其他链接对象模块使用。

global _start 让_start符号成为可见的标示符,这样链接器就知道跳转到程序中的什么地方并开始执行。linux寻找这个 _start标签作为程序的默认进入点。

c程序在调用print函数时,调用者c_func会将参数依次从右往左入栈,然后将返回地址入栈;在print函数里,要遵守函数的调用约定,字符串的起始地址存放在[ebp + 8]处,字符串的长度存放在[ebp + 12] 处。

c语言与汇编语言在满足以下条件时可混合编程

遵循相同的函数调用约定

遵循相同的目标文件格式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值