【发布时间】:2014-11-03 19:53:44
【问题描述】:
我在 c 中使用内联汇编块对数组进行排序的一段代码存在问题。
我的完整代码是这样的:
#include <stdio.h>
#define n 20
int main()
{
int array[n];
int i;
int swapped;
printf("Enter the elements one by one \n");
for (i = 0; i < n; i++)
{
scanf("%d", &array[i]);
}
printf("Input array elements \n");
for (i = 0; i < n ; i++)
{
printf("%d\n", array[i]);
}
/* Bubble sorting begins */
do
{
swapped = 0;
for (i = 1; i < n; i++)
{
/*
if (array[i] < array [i-1])
{
swapped =1;
int temp = array [i-1];
array [i-1] = array [i];
array[i] = temp;
}
*/
//body of the for loop
//converted to assembly
__asm__ __volatile__("cmp %0, %1;"
"jge DONE;"
"mov eax, %0;"
"mov %0, %1;"
"mov %1, eax;"
"mov %2, 1;"
"DONE: "
: "+r" (array[i]), "+r" (array[i-1]), "=r" (swapped)
: //no input
: "eax", "cc"
);
}
} while (swapped > 0);
printf("Sorted array is...\n");
for (i = 0; i < n; i++)
{
printf("%d\n", array[i]);
}
return 0;
}
由于某种原因,do while 变成了一个无限循环,但是当我将 swapped 变量的修饰符更改为 "+r" (swapped) 时,它可以工作。我查看了两种情况下生成的汇编代码(-save-temp),除了在使用“+r”的情况下将swapped 变量移动到寄存器之外没有注意到任何其他内容,这是预期的。
为什么我需要使用"+r"?
【问题讨论】:
-
我会害怕写这样的跳跃。想象一下编译器展开循环,它会跳转到哪里?另外,为什么要为此编写内联汇编?编译器应该从 C 代码中生成更好的代码。
-
你用
-masm=intel编译吗?我看不到你的命令行。 -
好吧,我在这里的唯一目的是学习 GCC 内联汇编。此外,我使用了 volatile 并使用 -O0 编译了代码,只是为了防止这些优化。
-
如果您担心扩展,可以使用 %=,例如:
jge DONE%=;和DONE%=:。这将扩展为一个唯一编号(请参阅gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#AssemblerTemplate 下的“其他格式字符串”)。此外,如果您使用符号名称,您可能会发现代码更易于阅读(即将"=r" (swapped)更改为[swapped] "=r" (swapped),然后使用%[swapped]而不是%2)。最后,如果您使用 gcc -S 输出 asm,您将看到所有命令一起运行。考虑使用\n\t而不是;。 FWIW。
标签: c gcc assembly x86 inline-assembly