在GNU C内联汇编中与push/assign/pop交换? [英] Swap with push / assignment / pop in GNU C inline assembly?

查看:63
本文介绍了在GNU C内联汇编中与push/assign/pop交换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里阅读一些答案和问题,并不断提出这个建议,但是我注意到,在使用Intel和GCC编译器的Windows上,没有人真正地确切地"解释了您需要做什么.以下正是我要尝试做的事情.

I was reading some answers and questions on here and kept coming up with this suggestion but I noticed no one ever actually explained "exactly" what you need to do to do it, On Windows using Intel and GCC compiler. Commented below is exactly what I am trying to do.

#include <stdio.h>

int main()
{
    int x = 1;
    int y = 2;
    //assembly code begin
    /*
      push x into stack; < Need Help
      x=y;               < With This
      pop stack into y;  < Please
    */
    //assembly code end
    printf("x=%d,y=%d",x,y);
    getchar();
    return 0;
}

推荐答案

如果要在带有红色区域的系统上移植,则不能仅仅从内联asm安全地推送/弹出.这包括每个非Windows x86-64平台.(无法告诉gcc您想要破坏它).好吧,您可以先添加rsp,-128 来跳过红色区域,然后再推送/弹出任何内容,然后再将其恢复.但是然后您就不能使用"m" 约束,因为编译器可能会使用相对于RSP的相对寻址,并带有假定未修改RSP的偏移量.

You can't just push/pop safely from inline asm, if it's going to be portable to systems with a red-zone. That includes every non-Windows x86-64 platform. (There's no way to tell gcc you want to clobber it). Well, you could add rsp, -128 first to skip past the red-zone before pushing/popping anything, then restore it later. But then you can't use an "m" constraints, because the compiler might use RSP-relative addressing with offsets that assume RSP hasn't been modified.

但这确实是在嵌入式asm中做的可笑的事情.

But really this is a ridiculous thing to be doing in inline asm.

以下是使用inline-asm交换两个C变量的方法:

Here's how you use inline-asm to swap two C variables:

#include <stdio.h>

int main()
{
    int x = 1;
    int y = 2;

    asm(""                  // no actual instructions.
        : "=r"(y), "=r"(x)   // request both outputs in the compiler's choice of register
        :  "0"(x),  "1"(y)   // matching constraints: request each input in the same register as the other output
        );
    // apparently "=m" doesn't compile: you can't use a matching constraint on a memory operand

    printf("x=%d,y=%d\n",x,y);
    // getchar();  // Set up your terminal not to close after the program exits if you want similar behaviour: don't embed it into your programs
    return 0;
}

gcc -O3从 Godbolt编译器浏览器:

.section .rodata
.LC0:
    .string "x=%d,y=%d"
.section .text
main:
    sub     rsp, 8
    mov     edi, OFFSET FLAT:.LC0
    xor     eax, eax
    mov     edx, 1
    mov     esi, 2
#APP
# 8 "/tmp/gcc-explorer-compiler116814-16347-5i3lz1/example.cpp" 1
            # I used "\n" instead of just "" so we could see exactly where our inline-asm code ended up.

# 0 "" 2
#NO_APP
    call    printf
    xor     eax, eax
    add     rsp, 8
    ret

C变量是一个高级概念;无需花费任何成本就可以确定相同的寄存器现在在逻辑上拥有不同的命名变量,而无需在不更改varname-> register映射的情况下交换寄存器内容.

C variables are a high level concept; it doesn't cost anything to decide that the same registers now logically hold different named variables, instead of swapping the register contents without changing the varname->register mapping.

手写asm时,请使用注释来跟踪不同寄存器或向量寄存器部分的当前逻辑含义.

inline-asm也不在inline-asm块之外导致任何额外的指令,因此在这种情况下它是非常有效的.尽管如此,编译器仍然看不到它,也不知道值仍然是1和2,因此进一步的常量传播将被击败. https://gcc.gnu.org/wiki/DontUseInlineAsm

The inline-asm didn't lead to any extra instructions outside the inline-asm block either, so it's perfectly efficient in this case. Still, the compiler can't see through it, and doesn't know that the values are still 1 and 2, so further constant-propagation would be defeated. https://gcc.gnu.org/wiki/DontUseInlineAsm

这篇关于在GNU C内联汇编中与push/assign/pop交换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆