Набор инструкций x86-64, синтаксис AT & T, путаница с символами LEA и скобками - PullRequest
0 голосов
/ 19 апреля 2020

Мне сказали, что lea% rax,% rdx является недопустимым синтаксисом, так как источник должен быть в скобках, т.е. lea (% rax),% rdx

Я думаю, что я явно неправильно понял оба Леа и назначение скобок.

Я думал, что lea% rax,% rdx переместит адрес памяти, хранящийся в% rax, в% rdx, но, очевидно, это то, что делает lea (% rax),% rdx?

Что меня смущает, так это то, что я думал, что скобки означают переход к адресу в памяти и получение значения по этому адресу. Поэтому с помощью скобок lea будет перемещать значение из адреса памяти, хранящегося в% rax, в регистр назначения.

Поэтому я подумал, что lea% rax,% rdx будет использоваться, если вы просто захотите переместить адрес хранится в% rax в% rdx

Может ли кто-нибудь объяснить мне значение скобок в случае инструкции по выходу?

1 Ответ

1 голос
/ 19 апреля 2020

Никогда на самом деле не используйте lea (%rax), %rdx. Вместо этого используйте mov %rax, %rdx, поскольку процессоры запускают его более эффективно, и оба способа копируют регистр значение (независимо от того, является ли это значение действительным указателем или нет).

LEA может работать только на режим адресации памяти, а не пустой регистр. LEA вроде «отменяет» скобки, беря результат вычисления адреса вместо значения из памяти по этому адресу. Этого не может произойти, если вначале не было операнда памяти.

Это позволяет использовать его для выполнения операций сдвига / добавления над произвольными значениями, независимо от того, являются они действительными указателями или нет: Использование LEA для значений, которые не являются адресами / указателями? LEA использует синтаксис операнда памяти и машинный код для кодирования операции сдвига / добавления в одну инструкцию, используя обычное кодирование в режиме адресации x86 что аппаратное обеспечение процессора уже знает, как декодировать.


По сравнению с mov, это похоже на C & оператор адресации. И вы не можете взять адрес реестра. (Или в C переменной register.) Вы можете использовать ее только для отмены уровня косвенности.

  register char *rax = ...;

  register char dl = *rax;       // mov   (%rax), %dl
  register char *rcx = rax;      // mov   %rax, %rcx
  register char *rdi = &rax[0];  // lea   (%rax), %rdi  // never do this, mov is more efficient
  register char *rbx = &rax[rdx*4 + 1234];  // lea 1234(%rax, %rdx, 4), %rbx  // a real use-case

  register char **rsi = &rax;    // lea %rax, %rsi   // ERROR: can't take the address of a register

Конечно, если вы спросили фактический C компилятор чтобы скомпилировать это, вы получите mov %rax, %rdi, а не lea (%rax), %rdi, даже если это не оптимизирует код. Это с точки зрения концептуальных эквивалентов, использующих синтаксис C и операторы для объяснения asm, а не для того, чтобы показать, как что-то будет или должно на самом деле компилироваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...