如何编写一个内联gnu扩展程序集的短块来交换两个整数变量的值?

问题描述 投票:2回答:1

为了娱乐,我正在使用带有32位Linux目标的x86的AT&T语法学习gnu扩展汇编。我刚刚花了最后三个小时编写两个可能的解决方案来交换两个整数变量ab的值的挑战,我的解决方案都没有完全解决我的问题。首先,让我们更详细地看一下我的TODO障碍:

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

c gcc x86 gnu inline-assembly
1个回答
3
投票

以下是评论中的一些解决方案:

解决方案#0(最佳选择):https://gcc.gnu.org/wiki/DontUseInlineAsm 即使是零指令解决方案也会破坏常量传播,以及任何其他涉及gcc知道任何值的优化。它还强制编译器在该点同时将两个变量同时存储在寄存器中。在考虑使用inline-asm而不是builtins / intrinsics时,请始终牢记这些缺点。

解决方案#1:x86 xchg,没有临时注册,并且可以在AT&T和Intel语法模式下工作。 Costs about the same as 3 mov instructions在大多数Intel CPU上,或者在某些AMD上只有2 uop。

asm("xchg %0, %1;" : "+r" (a), "+r" (b));

解决方案#2:纯粹使用GNU C内联asm约束。 (奖金:可移植到所有架构)

asm("" : "=r" (a), "=r" (b) : "1" (a), "0" (b));

查看on the Godbolt compiler explorer中的所有三个解决方案,包括它们击败优化的示例:

int swap_constraints(int a, int b) {
    asm("" : "=r" (a), "=r" (b) : "1" (a), "0" (b));
    return a;
}

// Demonstrate the optimization-defeating behaviour:
int swap_constraints_constants(void) {
  int a = 10, b = 20;
  return swap_constraints(a, b) + 15;
}

swap_constraints_constants:
    movl    $10, %edx
    movl    $20, %eax
    addl    $15, %eax
    ret

与纯C交换相比:

swap_noasm_constants:
    movl    $35, %eax    # the add is done at compile-time, and `a` is optimized away as unused.
    ret
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.