Как вы понимаете форму 'REX.W + B8+ rd io' для сборки x86-64?

Первоначально я пытался сгенерировать байты для немедленного перемещения в 64-битный регистр. Конкретная операция, которую я хотел, была

mov rdi, 0x1337

Используя https://www.felixcloutier.com/x86/mov, единственными расширенными инструкциями без знака, которые я видел, были

REX.W + B8+ rd io

Это смутило меня, поэтому я создал небольшую программу сборки, чтобы посмотреть, что будет генерировать ассемблер.

          global    _start

          section   .text
_start:   
          mov       rdi, 0x1337 
          syscall                           
          mov       rax, 60                 
          xor       rdi, rdi                
          syscall                           

Пришлось отключить оптимизации, чтобы был переход в 64-битный регистр. Поэтому я скомпилировал с nasm -felf64 -O0 main.asm && ld main.o и сгенерировал a.out. Я смотрю на objdump -M intel -d ./a.out и эту строку

48 bf 37 13 00 00 00    movabs rdi,0x1337  

Эта линия совсем не похожа

REX.W + B8+ rd io

мне? Кроме того, после некоторого исследовать я увидел, что команда должна быть 10 байт. Как вы получаете это от REX.W + B8+ rd io?

Кстати, почему бы и нет mov edi, 0x1337? Тот же эффект, меньшее кодирование.

harold 07.04.2022 00:36

@harold В итоге я сделал это, но я просто запутался в кодировке инструкций. REX.W + B8+ rd io выглядит очень необычно для меня, и я хотел бы это понять.

Happy Jerry 07.04.2022 00:57

Вы пропустили objdump -d -w, чтобы не переносить длинные инструкции, например 10-байтовые mov r64, imm64. См. также Разница между movq и movabsq в x86-64. (Кстати, вы можете получить это, не отключая оптимизацию NASM с помощью mov rdi, strict qword 0x1337. См. Почему NASM на Linux меняет регистры в сборке x86_64). Оба эти ответа имеют отношение к пониманию доступных форм MOV и того, как они работают в машинном коде.

Peter Cordes 07.04.2022 02:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
43
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

B8+ rd означает, что операнд (регистр) закодирован в младших 3 битах кода операции, а не в байте ModR/M.

Из Руководства разработчика программного обеспечения Intel,

+rb, +rw, +rd, +ro — Indicated the lower 3 bits of the opcode byte is used to encode the register operand without a modR/M byte. The instruction lists the corresponding hexadecimal value of the opcode byte with low 3 bits as 000b. In non-64-bit mode, a register code, from 0 through 7, is added to the hexadecimal value of the opcode byte. In 64-bit mode, indicates the four bit field of REX.b and opcode[2:0] field encodes the register operand of the instruction. “+ro” is applicable only in 64-bit mode.

Похоже, что Intel хотела использовать +ro для 64-битных операндов, закодированных таким образом, но на самом деле этого не сделала. Не только в лемме mov, но где угодно, насколько я мог найти. Например, 64-битные push и pop могли иметь + ro, но у них также есть + rd. А "Indicateг" скорее всего опечатка, в остальном тексте используется настоящее время.

Регистр (e/r)di имеет номер 7, а B8 + 7 = BF объясняет код операции.

io означает непосредственное qword (o для octo, возможно, как в 8 байтах?).

Префикс REX (40 для базового префикса, +8 для установки бита W, опционально +1 для установки бита B для доступа к R8..R15), код операции, байт нет ModR/M и 8-байтовый непосредственный, добавить до 10 байт.

Откуда взялось «40 для базового префикса, +8 для установки бита W»? Как вы узнали, что нужно установить бит W и добавить к нему 8?

Happy Jerry 07.04.2022 01:33

@HappyJerry REX.W в столбце кодирования указывает, что бит W должен быть установлен (имеет смысл: иначе это будет 32-битный mov), и это бит, который соответствует 8. REX без установленных флагов равен 40, REX с установленным битом W — это 48, которые вы видели.

harold 07.04.2022 01:38

Таким образом, REX используется для обозначения регистров. А бит W указывает, используете ли вы 32-битный или 64-битный регистр? Если бы я использовал регистр R9, флаг B был бы установлен. И первый байт будет 49. Что касается байта ModR/M, он используется, когда используется операнд памяти. Значит ли это, что используется любая форма r/m64, r/m32 или r/m16, есть вероятность, что используется байт ModR/M. Если r/mX является ячейкой памяти или смещением

Happy Jerry 07.04.2022 02:04

@HappyJerry ModR/M также обычно используется для кодирования регистровых операндов, инструкции с кодировкой +rd, безусловно, составляют меньшинство. Для большинства инструкций требуется байт modR/M.

harold 07.04.2022 02:18

@harold: Ха, я никогда не замечал такого использования o для oct-байт. В другом месте, например. cqo мнемоника, Intel использует o для 16-байтового окт-слово.

Peter Cordes 07.04.2022 02:25

@PeterCordes Спасибо. Единственное, чего я не вижу по этим ссылкам, так это того, что означает /0. Например ADD rm/32 imm32 это 81 /0 id

Happy Jerry 07.04.2022 03:14

@HappyJerry: см. мой ответ на Как читать нотацию Intel Opcode для части /0, используя ModRM.r в качестве дополнительных битов кода операции.

Peter Cordes 07.04.2022 03:23

@PeterCordes Итак, /0 - это поле reg в байте ModR/M? Другими словами, косая черта может быть от /0 до /7.

Happy Jerry 07.04.2022 06:54

Другие вопросы по теме