gpt4 book ai didi

c - MinGW 内联汇编中的 "Error: backward ref to unknown label..."

转载 作者:太空宇宙 更新时间:2023-11-03 23:57:19 28 4
gpt4 key购买 nike

我又一次玩起了 MinGW 内联汇编。

#include <stdio.h>

int foobar(int);

int main(){
int n = 0;
printf("Number: ");
scanf("%d", &n);
printf("\n%d",foobar(n));
return 0;
}

int foobar(int num){
int result = 0;
asm(".intel_syntax noprefix\n");
asm("mov eax, num\n");
asm("add eax, 110b\n");
asm("sub eax, 2\n");
asm("mov result, eax\n");
return result;
}

编译它:

C:\Users\Andre\Codes>gcc asmtest.c -o asmtest -masm=intel

哎呀,有错误:

C:\Users\Andre\AppData\Local\Temp\ccqny4yb.s: Assembler messages: C:\Users\Andre\AppData\Local\Temp\ccqny4yb.s:53: Error: backward ref to unknown label "110:"

这是怎么回事?我认为我的代码已经有效?

最佳答案

GCC 最适用于 AT&T 风格的汇编,而 GAS 并没有实现所有的 Intel 语法。您的直接问题来自 110b 没有被解释为数字,但这还不是全部。

您不能在 GCC 的内联汇编语法中直接引用变量。你必须这样写(使用默认的 -masm=att):

int foobar(int num) {
int result;
asm("mov %1, %%eax\n\t"
"add $6, %%eax\n\t"
"sub $2, %%eax\n\t"
"mov %%eax, %0"
: "=g" (result)
: "g" (num)
: "eax", "cc");
return result;
}

第一个冒号之后是逗号分隔的输出操作数列表。因为 "=g"(result) 是第一个约束,所以 result 获得别名 %0"=g" 向 GCC 表明 %0 可以是任何通用寄存器或内存,并且只会被写入。 (+ 而不是 = 表示读写。GCC 可能会决定将同一个寄存器重新用于多种用途,因此您必须明确告诉它一切如何将被使用。)

在第二个冒号之后是逗号分隔的输入操作数列表。因为 "g"(num) 是第二个约束,所以 num 获得别名 %1"g" 表示它只会被读取。

在第三个冒号之后是逗号分隔的 clobbers 列表。这告诉 GCC 内联汇编可能会更改这些寄存器/内存,即使它们既不是输入也不是输出,因此 GCC 必须通过内联汇编重新加载它保存在其中的任何信息。在这里,我们显然更改了%eax,条件代码(标志)寄存器也受到了add/sub的影响。

查看编译器生成的程序集:

$ cc -S -o- -m32 asmtest.c | sed -n /globl.foobar/,/-foobar/p.globl foobar        .type   foobar, @functionfoobar:        pushl   %ebp        movl    %esp, %ebp        subl    $16, %esp#APP# 15 "asmtest.c" 1        mov 8(%ebp), %eax        add $6, %eax        sub $2, %eax        mov %eax, -4(%ebp)# 0 "" 2#NO_APP        movl    -4(%ebp), %eax        leave        ret        .size   foobar, .-foobar

编译器决定直接使用numresult 的堆栈位置。如果我们使用 :"=r":"r" 约束(这意味着只允许寄存器)而不是 :"=g":"g"(它允许寄存器或内存位置),编译器会在内联汇编之前/之后将它们复制到/从寄存器中复制。

$ cc -S -o- -m32 asmtest.c | sed -n /globl.foobar/,/-foobar/p.globl foobar        .type   foobar, @functionfoobar:        pushl   %ebp        movl    %esp, %ebp        subl    $16, %esp        movl    8(%ebp), %edx#APP# 15 "asmtest.c" 1        mov %edx, %eax        add $6, %eax        sub $2, %eax        mov %eax, %edx# 0 "" 2#NO_APP        movl    %edx, -4(%ebp)        movl    -4(%ebp), %eax        leave        ret        .size   foobar, .-foobar

如果真的要使用Intel语法,把它放在一个单独的.s源文件中,用NASM独立组装。 ,然后将对象链接在一起。

$ cat asmtest.c#include <stdio.h>int foobar(int);/* int foobar(int) __attribute__((fastcall)); */int main() {    int n = 0;    printf("Number: ");    scanf("%d", &n);    printf("%d\n", foobar(n));    return 0;}$ cat foobar.sglobal foobarfoobar:        mov eax,[esp+4]  # take this line out if C prototype is marked fastcall        sub eax,110b        add eax,2        ret$ nasm -f elf foobar.s$ cc -m32 asmtest.c foobar.o$ ./a.outNumber: 3026

(尽管 -f elf 对于 Windows 不正确。也许 -f win32?由于 Windows 的愚蠢,您可能不得不使用名称 _foobar 在汇编中。)

关于c - MinGW 内联汇编中的 "Error: backward ref to unknown label...",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2345874/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com