Страницы

Поиск по вопросам

среда, 5 февраля 2020 г.

Семантика перемещения на уровне ассемблера

#cpp #ассемблер


C++:

 #include 
    int main()
    {
        int a =10;
        int b = std::move(a);
    }


ASM:

std::remove_reference::type&& std::move(int&):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     rax, QWORD PTR [rbp-8]
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-8], 10
        lea     rax, [rbp-8]
        mov     rdi, rax
        call    std::remove_reference::type&& std::move(int&)
        mov     eax, DWORD PTR [rax]
        mov     DWORD PTR [rbp-4], eax
        mov     eax, 0
        leave
        ret


Как семантика перемещения работает на уровне ассемблера?
    


Ответы

Ответ 1



Семантика перемещения - концепция уровня языка, построенная вокруг типа rvalue-ссылки, категории xvalue и связанных с этим типом правил разрешения перегрузок ("overload resolution"). На уровне ассемблера нет никакой разницы между rvalue-ссылкой и lvalue-ссылкой. Все фундаментальные типы всегда безусловно копируются, независимо того, является ли правая часть rvalue-ссылкой или нет. Для пользовательских же типов все определяется тем, что вы сами напишете в соответствующих перегруженных функциях. Что вы напишете - то и получится в ассемблере. Другими словами, нет никакой "семантики перемещения" на уровне ассемблера. На уровне ассемблера есть только копирование. А вам, пользователю языка, в рамках языковой "семантики перемещения" лишь дается возможность выбрать, что (и как) копировать, а что не копировать. В приведенном вами коде вы видите лишь не устраненный оптимизатором вызов функции std::move, которая "ничего не делает", а просто приводит свой аргумент к типу rvalue-ссылки. В коде, сгенерированном "начистовую" все эти "ничего не делающие" вызовы должны быть устранены и код должен быть эквивалентен простому int a = 10; int b = a; Например void foo(int &a, int &b, int &c, int &d) { a = std::move(b); c = d; } при компиляции g++ -O3 дает foo(int&, int&, int&, int&): // a = std::move(b); mov eax, DWORD PTR [rsi] mov DWORD PTR [rdi], eax // c = d; mov eax, DWORD PTR [rcx] mov DWORD PTR [rdx], eax // ret https://godbolt.org/z/O2WAmU

Комментариев нет:

Отправить комментарий