【发布时间】:2012-01-18 10:51:24
【问题描述】:
我正在尝试使用 GCC 的内联汇编器熟悉 x86 汇编。我正在尝试添加两个数字(a 和b)并将结果存储在c 中。我有四种略有不同的尝试,其中三种有效;最后一个没有产生预期的结果。
前两个例子使用了一个中间寄存器,它们都可以正常工作。第三个和第四个示例尝试在不使用中间寄存器的情况下直接将两个值相加,但结果会因优化级别和我添加输入值的顺序而异。我哪里错了?
环境是:
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
首先,变量声明如下:
int a = 4;
int b = 7;
int c;
示例 1:
asm(" movl %1,%%eax;"
" addl %2,%%eax;"
" movl %%eax,%0;"
: "=r" (c)
: "r" (a), "r" (b)
: "%eax"
);
printf("a=%d, b=%d, c=%d\n", a, b, c);
// output: a=4, b=7, c=11
示例 2:
asm(" movl %2,%%eax;"
" addl %1,%%eax;"
" movl %%eax,%0;"
: "=r" (c)
: "r" (a), "r" (b)
: "%eax"
);
printf("a=%d, b=%d, c=%d\n", a, b, c);
// output: a=4, b=7, c=11
示例 3:
asm(" movl %2,%0;"
" addl %1,%0;"
: "=r" (c)
: "r" (a), "r" (b)
);
printf("a=%d, b=%d, c=%d\n", a, b, c);
// output with -O0: a=4, b=7, c=11
// output with -O3: a=4, b=7, c=14
示例 4:
// this one appears to calculate a+a instead of a+b
asm(" movl %1,%0;"
" addl %2,%0;"
: "=r" (c)
: "r" (a), "r" (b)
);
printf("a=%d, b=%d, c=%d\n", a, b, c);
// output with -O0: a=4, b=7, c=8
// output with -O3: a=4, b=7, c=11
已解决。 Matthew Slattery's answer 是正确的。之前,它试图为b 和c 重用eax:
movl -4(%rbp), %edx
movl -8(%rbp), %eax
movl %edx, %eax
addl %eax, %eax
随着 Matthew 建议的修复到位,它现在使用 ecx 来单独保存 c。
movl -4(%rbp), %edx
movl -8(%rbp), %eax
movl %edx, %ecx
addl %eax, %ecx
【问题讨论】:
-
对我来说效果很好,无论是否启用优化。尝试使用 -S 进行编译,以获得汇编语言列表。然后你可以看到正在使用哪些寄存器。
-
刚刚注意到我得到不同的结果取决于优化级别。使用新输出更新了代码示例。
-
那么组装清单告诉你什么?
-
使用修复前后的程序集列表更新了问题。
标签: gcc x86 inline-assembly