Why does issuing empty asm commands swap variables?

牧云@^-^@ 提交于 2021-02-07 17:34:22

问题


So I was messing around with inline assembly and compiled this using GCC 9. The result was that the two variables a and b were swapped without actually issuing any direct commands.

#include<cstdio>
int main(){
    int a(1),b(2),c(3);
    asm ("": "=r"(c):"r"(a));
    asm ("": "=r"(a):"r"(b));
    asm ("": "=r"(b):"r"(c));
    printf("%d %d %d", a,b,c);
}

Can somebody explain what is going on here?


回答1:


Basically random chance of variable allocation. (Or actually GCC's internal machinery's first choices).

You used output-only "=r" asm operands but then your asm template doesn't actually write that register so you get whatever value was sitting in the register GCC picked.

This is a lot like C undefined behaviour for using an uninitialized varible.

To see what happened, put asm comments in the asm template that expand %0 and %1 inside the template inside an asm comment. This will have no impact on how GCC does register allocation: it doesn't care if the template uses the registers it picks implicitly or explicitly; it's up to you to write a useful template and match that to the operand constraints.

With your code on the Godbolt compiler explorer, with gcc9.2 -O3 -fverbose-asm:

.intel_syntax noprefix
.LC0:
        .string "%d %d %d"
main:
        sub     rsp, 8    #,
        mov     edi, OFFSET FLAT:.LC0     #,
        xor     eax, eax  #
        mov     ecx, 1    # tmp87,
        mov     esi, 2    # tmp89,
        nop  #ecx ecx   # c, tmp87
        nop  #esi esi   # a, tmp89
        nop  #edx ecx   # b, c
        call    printf  #
        xor     eax, eax  #
        add     rsp, 8    #,
        ret     

(Instead of a bare asm comment, I put the comments on NOP instructions like
asm ("nop #%0 %1": "=r"(c):"r"(a)); so compiler-explorer filtering wouldn't remove them. asm templates are pure text substitution before feeding it to the assembler so again this is still exactly equivalent to how GCC would have compiled your original source with the same options.)

In the first 2 cases, gcc decided to pick the same register for output as for input so those happened to work like assignments.

In the 3rd case, c was already in a register, and putting a 3 anywhere was optimized away because "=r"(c) overwrite that value before it was ever read.

Perhaps you were compiling with optimization disabled? You could do that too, and follow what happened. (Probably GCC would pick eax for both input and output each time). I normally don't bother looking at anti-optimized -O0 asm because its full of store/reload noise.



来源:https://stackoverflow.com/questions/58679320/why-does-issuing-empty-asm-commands-swap-variables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!