zoukankan      html  css  js  c++  java
  • 【转】GCC和NASM联合编译

    GCC不用说,C语言的编译器。NASM是一个x86的汇编器,用来编译汇编的。最近在研究GCC和NASM联合编译,为什么要研究二者的联合编译呢?GCC中能嵌套汇编代码啊?这是因为GCC中嵌套的汇编代码是AT&T的汇编代码不是Interl的。其语法格式实在是太复杂了,不是适合初学者(其实是我不会其语法)。下面我们结合一个例子来将二者如何联合使用。

    1.建立示例工程

    示例工程很简单,就下面三个文件:

    工程代码  收藏代码
    1. main.c         ---C代码  
    2. hello.asm    --- 汇编代码  
    3. Makefile      ---编译命令  

     其中Makefile的内容如下:

    Java代码  收藏代码
    1. all:  
    2.     nasm -f elf hello.asm -o hello.o  
    3.     gcc -o main main.c hello.o  

     其中nasm的参数 -f elf表示输出文件的格式为ELF格式。

     

    2.NASM和C互相调用对方的函数

    先看例子的代码:

    Nasm代码  收藏代码
    1. extern print_helloworld  
    2.   
    3. [section .text]  
    4. global print_two_hello_world  
    5. print_two_hello_world:    
    6.     call print_helloworld  
    7.     call print_helloworld  

     

    C代码  收藏代码
    1. #include "stdio.h"  
    2.   
    3. extern void print_two_hello_world();  
    4.   
    5. char *strhello = "Hello,world!\n";  
    6.   
    7. void print_helloworld ()  
    8. {  
    9.         printf ("%s",strhello);  
    10. }  
    11.   
    12. int  main ()  
    13. {  
    14.         print_two_hello_world();  
    15.         return 0;  
    16. }  

      首先看NASM代码,先导入一个外部函数print_helloworld(),此函数是C语言定义的一个函数。接下来是定义了一个函数print_two_hello_world,用global关键字导出使其可以在C中调用,函数的内容是调用了两次print_helloword()。

    在来看C代码,代码很简单就具体讲了,这里主要数一下我们将主函数放在了C代码中写,这时因为我们要使用C代码的函数库中的printf()函数,如果C代码中没有什么库的依赖可以将主函数放在汇编代码中,具体的实现请参考《自己动手写操作系统》一书。

    3.NASM和C互相调用对方的变量

    同样先看代码:

    Nasm代码  收藏代码
    1. global string  
    2. extern strhello  
    3. [section .data]  
    4. string:  
    5.     db 'I am Chinese.',0x0A,0x0  
    6. [section .text]  
    7.     global print_hello  
    8.     global cpy_mem  
    9. print_hello:      
    10.     mov edx, 13  
    11.     mov ecx,[strhello]  
    12.     mov ebx,1  
    13.     mov eax,4  
    14.     int 0x80  

     

    C代码  收藏代码
    1. #include "stdio.h"  
    2. #include "string.h"  
    3. extern char *string;  
    4. extern void print_hello();  
    5. extern cpy_mem (void *dest, int len);  
    6. char *strhello = "Hello,world!\n";  
    7. char *str = NULL;  
    8. int  
    9. main ()  
    10. {  
    11.         printf ("%x\n",&string);  
    12.         str = &string;  
    13.         printf ("%s", str);  
    14.          
    15.         print_hello ();  
    16.         return 0;  
    17. }  

     Make后的执行结果如下:

    具体的代码内容就部分析了,这里主要将两个关键的地方。

    1.在C语言中定义了一个strhello的字符串变量,在C语言中strhello表示的是字符串的首地址,比如字符串的地址是0xa00001,而strhello是个指针即4字节其地址为0xb00001, 在C语言中strhello表示的值是 0xa00001 字符串的首地址,但到了NASM中则表示的 strhello变量的首地址了 0xb00001,所以

    Nasm代码  收藏代码
    1. mov ecx,[strhello]  

     代码中加了中括号表示是内容,这一点一定要注意,否则会出错!!

    2.第二点要注意的是,在NASM中定义了一个字符串string  在C语言中导入的话,就是表示字符串的首地址,因此要引用该字符串一定要取其地址,不要直接转为(char*)类型直接用,否则出错,这是因为直接转的话,就将字符串的前4个字节转成了字符串指针,但该指针是不确定会出现段错误!

  • 相关阅读:
    Vue路由机制
    谷歌浏览器打不开应用商店的解决方法
    Vue报错——Component template should contain exactly one root element. If you are using vif on multiple elements, use velseif to chain them instead.
    Vue.js学习之——安装
    Vue使用axios无法读取data的解决办法
    关于localstorage存储JSON对象的问题
    2013年整体计划
    个人喜欢的警语收集
    Linux防火墙的关闭和开启
    Flex修改title 转载
  • 原文地址:https://www.cnblogs.com/jackyzzy/p/2981543.html
Copyright © 2011-2022 走看看