【问题标题】:gcc inline assembler: "leal 2(%%ebx,%%eax,$2),%1" doesn't assemble but it does without the $gcc 内联汇编器:"leal 2(%%ebx,%%eax,$2),%1" 不汇编,但没有 $
【发布时间】:2017-09-24 12:28:08
【问题描述】:

这是我第一次编写汇编代码。 一开始,我写了

#include<stdio.h>
int main(){
    int x,y;
    asm("movl $2,%eax");
    asm volatile(
                    "movl $1,%0\n\t"
                    "movl %0,%%ebx\n\t"
                    "leal 2(%%ebx,%%eax,$2),%1"
                    :"=m"(x),"=r"(y)
                    );
    printf("x is %d, y is %d\n",x,y);
    return 0;
}

gcc 5.4.0 编译器给出错误信息:

test.c: Assembler messages:
test.c:7: Error: bad or irreducible absolute expression
test.c:7: Error: expecting scale factor of 1, 2, 4, or 8: got `$2'

那我换个

"leal 2(%%ebx,%%eax,$2),%1"

"leal 2(%%ebx,%%eax,2),%1"

没关系。但是,$2 不等于 2 吗?

【问题讨论】:

  • 在这种语法中,数字必须不带$,这就是它的定义方式。通常 $ 表示一个常量,但由于在寻址模式中除了特定常量之外不能有任何其他内容,因此它不使用前缀来表示这是一个常量。
  • 仅供参考,在不告诉编译器的情况下破坏%ebx(带有破坏约束)将导致不可预测的结果。 (好吧,如果您使用 gcc -O2 -S 读取编译器的最终 asm 输出,则可以预测)。见stackoverflow.com/tags/inline-assembly/info

标签: gcc assembly att


【解决方案1】:

在 AT&T 语法中,美元符号$ 表示立即操作数。例如,它区分

add 16,%eax

(将地址16 的值添加到eax)来自

add $16,%eax

(将16 添加到eax)。请注意,这根本与整数常量无关。你也可以写

add foo,%eax

add $foo,%eax

foo 是一些符号。 disp(base,index,scale) 表示法表示使用SIB 寻址的内存操作数。 这种寻址模式中的三个部分中的每一个都有固定的用途,因此用任何东西装饰scale 是没有意义的。毕竟我们已经选择了寻址方式,为什么还要在括号内加上一个操作数类型的指示符呢?请注意,寄存器名称前的% 仍然是必需的,因为它将寄存器名称与宏或符号名称区分开来。

【讨论】:

    猜你喜欢
    • 2011-04-29
    • 1970-01-01
    • 2012-10-20
    • 2019-05-11
    • 2020-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多