c - 如何在 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
[...]
当然我做错了一些事情。你可以帮帮我吗?
谢谢。
解决方案
唔
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
尝试使用已编译的程序集作为起点通常会更痛苦,当然可以进行剪切和粘贴,但是会产生很多开销,并且机器生成的标签需要清理而不是从头开始。(我更喜欢反汇编和工作,而不是直接使用编译器输出)
推荐阅读
- android - Android Studio:无法添加新的 ui 元素
- java - AppCompatImageView 设置背景 android 17
- google-chrome-extension - 在 chrome 扩展中,如何从当前 chrome 用户以外的 gmail 用户获取访问令牌?
- scala - 如何在scala中实现Java“@Default.String”
- rabbitmq - 使用 HTTP API 发布到 RabbitMQ 队列
- matlab - 如何停止 Matlab 量化图形?
- android - 如何使用 kotlin 和 google maps utils 对 google map 中的标记进行聚类
- jquery - Jquery :: 2个数字的加法
- r - 从 sjPlot 包中更改 plot_model 中主持人的值
- c - OpenMP:当代码以普通用户身份运行时,“libgomp:线程创建失败:资源暂时不可用”