对于娱乐,我正在学习GNU扩展程序集,使用带有32位Linux目标的x86的AT & T语法。我刚刚花了最后三个小时编码两个可能的解决方案,以交换两个整数变量a
和b
的值,我的解决方案都不能完全解决我的问题。首先,让我们来看看我的TODO障碍在一些细节:如何编写一个内嵌gnu扩展程序集的短块来交换两个整数变量的值?
int main()
{
int a = 2, b = 1;
printf("a is %d, b is %d\n", a, b);
// TODO: swap a and b using extended assembly, and do not modify the program in any other way
printf("a is %d, b is %d\n", a, b);
}
阅读this HOWTO后,我写了下面的内联扩展汇编代码。这是我第一次尝试换整数:
asm volatile("movl %0, %%eax;"
"movl %1, %%ecx;"
"movl %%ecx, %0;"
: "=r" (a)
: "r" (b)
: "%eax", "%ecx");
asm volatile("movl %%eax, %0;"
: "=r" (b)
: "r" (a)
: "%eax", "%ecx");
我的理由是,设置A = B,我需要一个扩展组件调用从装配分离设置B = A。于是我编写了两个扩展的程序集调用,编译了我的代码,即gcc -m32 asmPractice.c,并运行了a.out。结果如下:
a为2,b为1
a为1,b为1
看怎么说也不能正常工作,然后我决定结合两个扩展汇编程序调用,并写了这一点:
asm volatile("movl %0, %%eax;"
"movl %1, %%ecx;"
"movl %%ecx, %0;"
"movl %%eax, %1;"
: "=r" (a)
: "r" (b));
重新编译和链接之后,我的代码仍无法正常交换两个值。你自己看。下面是我的结果:
a为2,b为1
a为1,b为1
既然你传递寄存器你可以只要做'xchg%0,%1'。使用移动只需要1个临时寄存器。将%0复制到该寄存器。然后将%1复制到%0,然后将临时寄存器复制到%1。临时将需要列在clobber列表中 –
另请参见XOR交换算法https://en.wikipedia.org/wiki/XOR_swap_algorithm –
您现有的行内汇编还存在问题,即a和b都是输入和输出。所以** both **应该使用读写约束''+ r“' –