Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2034011
  • 博文数量: 369
  • 博客积分: 10093
  • 博客等级: 上将
  • 技术积分: 4271
  • 用 户 组: 普通用户
  • 注册时间: 2005-03-21 00:59
文章分类

全部博文(369)

文章存档

2013年(1)

2011年(2)

2010年(10)

2009年(16)

2008年(33)

2007年(146)

2006年(160)

2005年(1)

分类: C/C++

2006-04-30 14:14:07

在有些情况下,我们不得不需要C和汇编同时上阵,各显神通。BootLoader和Kernel就是比较典型的例子,本文将就C语言和汇编语言混合编程做些简略说明。需要说明的是,这里所说的混合编程,并不是C语言中嵌入汇编,如需要相关资料,请自行查找。
知识回顾:
GCC编译流程是,先将C语言翻译成汇编语言(*.s),再编译成目标文件(*.o),最后执行连接,将目标文件连接成可执行文件。C语言编程中,经常需要调用函数,函数通常由三部分组成:函数名、参数、返回值。在混合编程中,需要注意的就是函数参数的传递和返回值的传递,这里直接给出结果,默认的情况下GCC是用栈来传递参数的,并且参数的压栈顺序是从最后一个参数向前依次压栈,而返回值保存在寄存器%eax中,在GCC的扩展中可以用附加属性__attribute__((regparm(n)))来指定有几个参数用寄存器传递,但是用寄存器传递的参数个数不能多余3个。用寄存器进行参数传递时,从第一个参数开始依次用寄存器%eax, %edx, %ecx来传递参数,未能用寄存器传递的参数,将从最后一个参数开始依次压栈,用栈来进行传递,返回值依旧保存在寄存器%eax中。
Linux下汇编:
Linux下的汇编用的是AT&T格式的I386汇编,要想一个汇编文件中的某个Label在其它文件中可见,则必须用.globl _lablel_name导出。
C语言下的函数和汇编下的Label:
实际上我们在C语言中定义的函数或者是全局变量在C语言翻译成汇编语言的后,和汇编语言导出的Label是等同的。但是名称可能发生变化,比如说C语言中的一个函数为void test(void),翻译成汇编语言就可能为_test,test,GCC在当前的Linux系统中,是翻译成test的,在Windows平台上的MinGwin中的GCC还是如以前一样,翻译成_test,至于为什么采用后者,一说为让交叉索引程序更容易生成交叉索引。
C语言调用汇编语言的例子:
File: main.c

#include

int main(void)
{
        int ret;

        ret = test(4);
        printf("%d\n", ret);

        return 0;
}
File: test.s
.text
        .globl  test
test:
        push    %ebp
        mov             %esp, %ebp

        mov             8(%esp), %eax
        imull   8(%esp), %eax

        mov             %ebp, %esp
        pop             %ebp
        ret
汇编语言调用C语言的例子:
File:main.c

#include

int test2(int val)
{
        return val * val;
}

int main(void)
{
        int ret;

        ret = test(4);
        printf("%d\n", ret);

        return 0;
}
File: test.s

.text
        .globl  test
test:
        push    %ebp
        mov             %esp, %ebp

        mov             8(%esp), %eax
        imull   8(%esp), %eax
        push    %eax
        call    test2

        mov             %ebp, %esp
        pop             %ebp
        ret

阅读(2922) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~