首页 > 解决方案 > 如何在 C 项目中添加汇编代码?

问题描述

我想编译一个简单的 C 项目,它在 ASM 文件中定义了一些外部函数。我的主文件是一个 C++,它调用了在程序集文件中定义的一些“外部“C””函数。

当我运行任务“g++ build active file”时,我收到一些关于“extern”的警告和一些关于 asm 文件中定义的函数的错误,告诉“未定义对 my_funcions 的引用”。

我的 C++ 文件包含一个像这样的“外部”:

[...]
extern "C" {
    // Subrutines en ASM
    void posCurScreenP1();
    void moveCursorP1();
    void openP1();
    void getMoveP1();
    void movContinuoP1();
    void openContinuousP1();
    void printChar_C(char c);
    int clearscreen_C();
    int printMenu_C();
    int gotoxy_C(int row_num, int col_num);
    char getch_C();
    int printBoard_C(int tries);
    void continue_C();
}
[...]

我的 asm 文件包含以下内容:

.586
.MODEL FLAT, C
; Funcions definides en C
printChar_C PROTO C, value:SDWORD
printInt_C PROTO C, value:SDWORD
clearscreen_C PROTO C
clearArea_C PROTO C, value:SDWORD, value1: SDWORD
printMenu_C PROTO C
gotoxy_C PROTO C, value:SDWORD, value1: SDWORD
getch_C PROTO C
printBoard_C PROTO C, value: DWORD
initialPosition_C PROTO C
.code   
[...]

当然我做错了一些事情。你可以帮帮我吗?

谢谢。

标签: cassemblyvisual-studio-code

解决方案


so.c

extern "C" int fun ( void );
int x;
int main()
{
    x=fun();
    return x;
}

乐趣.c

int fun ( void )
{
    return(5);
}

建造

gcc fun.c -O2 -c -o fun.o
g++ -O2 so.cpp fun.o -o so

没有错误

00000000004003e0 <main>:
  4003e0:   48 83 ec 08             sub    $0x8,%rsp
  4003e4:   e8 17 01 00 00          callq  400500 <fun>
  4003e9:   89 05 45 0c 20 00       mov    %eax,0x200c45(%rip)        # 601034 <x>
  4003ef:   48 83 c4 08             add    $0x8,%rsp
  4003f3:   c3                      retq   


0000000000400500 <fun>:
  400500:   b8 05 00 00 00          mov    $0x5,%eax
  400505:   c3                      retq   

可以,然后呢

更多乐趣

.globl fun
fun:
    mov $0x5,%eax
    retq

建造

as morefun.s -o morefun.o
g++ -O2 so.cpp morefun.o -o so

没有错误,

检查

00000000004003e0 <main>:
  4003e0:   48 83 ec 08             sub    $0x8,%rsp
  4003e4:   e8 0d 01 00 00          callq  4004f6 <fun>
  4003e9:   89 05 45 0c 20 00       mov    %eax,0x200c45(%rip)        # 601034 <x>
  4003ef:   48 83 c4 08             add    $0x8,%rsp
  4003f3:   c3                      retq   

0000000004004f6 <fun>:
  4004f6:   b8 05 00 00 00          mov    $0x5,%eax
  4004fb:   c3                      retq   

看起来仍然不错,通过使其看起来像 C 函数,将程序集添加到 C++ 项目没有问题。

其他路径

int fun ( void )
{
    return(5);
}

gnu 和大多数其他理智的编译器编译为 asm 然后调用汇编器,这样你就可以看到它们是如何做到的并重复

gcc -O2 -S fun.c -o fun.s
as fun.s -o fun.o

猫的乐趣.s

    .file   "fun.c"
    .section    .text.unlikely,"ax",@progbits
.LCOLDB0:
    .text
.LHOTB0:
    .p2align 4,,15
    .globl  fun
    .type   fun, @function
fun:
.LFB0:
    .cfi_startproc
    movl    $5, %eax
    ret
    .cfi_endproc
.LFE0:
    .size   fun, .-fun
    .section    .text.unlikely
.LCOLDE0:
    .text
.LHOTE0:
    .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609"
    .section    .note.GNU-stack,"",@progbits

或使用保存临时。

gcc -O2 -c -save-temps fun.c -o fun.o

查看编译器生成的 asm

尝试使用已编译的程序集作为起点通常会更痛苦,当然可以进行剪切和粘贴,但是会产生很多开销,并且机器生成的标签需要清理而不是从头开始。(我更喜欢反汇编和工作,而不是直接使用编译器输出)


推荐阅读