gcc与nasm联合编译

最近碰到c与asm混合的代码,由于之前没有相关的经验,编译起来非常费力。这里将遇到的一些坑总结一下,再mac平台下使用gcc和nasm编译。

一、相关代码

c代码如下:

#include 

int add(int a, int b);

int main(int argc, char **argv)
{
    printf("%d\n", add(1, 8));
    return 0;
}

asm代码如下:

global add

section .data
section .text
add:
    mov   eax, [esp+4]   ; argument 1
    add   eax, [esp+8]   ; argument 2
    ret

二、开始编译

将c和asm编译成目标文件:

nasm -f macho32 demo.asm
gcc -m 32 -c main.c

说明:
1. -f macho32:指定文件格式类型;
2. -m32:指定生成程序的位数;
3. 当文件类型或者位数不匹配,链接是会提示如下:

ld: warning: ignoring file demo.o, file was built for i386 which is not the architecture being linked (x86_64): demo.o

三、链接

gcc -m32 -o main demo.o main.o

结果报错,提示信息为:

Undefined symbols for architecture i386:
  "_add", referenced from:
      _main in main.o
ld: symbol(s) not found for architecture i386

已经在asm文件中实现了add,链接时居然找不到。google很久才发现需要在as中add函数前加下划线,修改后的asm文件如下:

global _add
section .data
section .text
_add:
    mov   eax, [esp+4]   ; argument 1
    add   eax, [esp+8]   ; argument 2
    ret

重新编译链接,程序成功运行。

四、关于_下划线的思考

如果asm文件中仅仅是一两个函数,那可以直接在函数前面加下划线。但如果是多个文件或者n个函数,这种方式不可取。查阅nasm文档后,发现可以用–prefix给全局参数或者函数添加前缀,即使用

nasm -f macho32 --prefix _ demo.asm

编译。

五、使用cmake编译

如果利用cmake编译,Cmakelists.txt如下:

cmake_minimum_required(VERSION 3.10)
project(demo)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_ASM_NASM_OBJECT_FORMAT "macho32")
enable_language(ASM_NASM)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS}  --prefix _")
set(CMAKE_VERBOSE_MAKEFILE  on)
add_executable(demo main.c demo.asm)

备注:

  • enable_language(ASM_NASM)使用masm编译asm文件;
  • 使用CMAKE_ASM_NASM_OBJECT_FORMAT指定asm编译的目标文件格式;
  • 使用CMAKE_ASM_NASM_FLAGS来指定nasm编译的FLAGS.

你可能感兴趣的:(乱七八糟)