Как выполняется __asm ​​__volatile? - PullRequest
0 голосов
/ 20 марта 2020
gcc_inline void
lcr0(uint32_t val)
{
    __asm __volatile("movl %0,%%cr0" : : "r" (val));
}

В приведенном выше коде я не уверен, где val вставляется в строку сборки. Заменяет ли val% c в строке?

Если возможно, кто-нибудь может уточнить, что делает : : "r"?

1 Ответ

1 голос
/ 20 марта 2020

"r" означает, что вы указываете %0 как регистр (как вход). (val) означает, что вы указываете, что регистр должен содержать значение val. Таким образом, компилятор выделит регистр и убедится, что он содержит val. Для x86_64 первый аргумент функции будет в %edi / %rdi, и это то, что %0 расширится до.


Я исправлен ...

... если функция не встроена , val будет передано в edi / rdi, но может быть перетасовано до asm, но "r" вызовет компилятор, чтобы он был в каком-то регистре для asm. (См. Эффект -O0 ниже).

Также может быть встроена функция, которая не объявлена ​​/ не определена как встроенная, на более высоких уровнях оптимизации.

Я отмечаю, что это возможно только чтение / запись CR0 в / из регистра общего назначения, а затем только на уровне привилегий 0. @PeterCordes отмечает, что "memory" clobber, вероятно, будет хорошей идеей. Очевидно, что изменение CR0 может иметь действительно захватывающие побочные эффекты!


Когда я попытался сделать это на -O0, я обнаружил, что простой inline был проигнорирован, и функция, скомпилированная для x86_64 для:

   lcr0:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        movl %eax,%cr0
        nop
        popq    %rbp
        ret

Я полагаю, что gcc_inline может включать __attribute__((__always_inline__)), и в этом случае даже в -O0 lcr0 встроено - но с большим количеством прекрасных стековых бизнесов. На этот раз для x86:

  main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $16, %esp
        movl    12(%ebp), %eax
        movl    (%eax), %eax
        movl    (%eax), %eax
        movl    %eax, -4(%ebp)
        movl    -4(%ebp), %eax
        movl    %eax, -8(%ebp)
        movl    -8(%ebp), %eax
        movl %eax,%cr0
        nop
        movl    $0, %eax
        leave
        ret
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...