Кодировка «MOV EAX, moffs32» на x86-64

Я наткнулся на инструкцию «MOV EAX, moffs32», пытаясь понять x86-64.

Насколько я могу судить, эта инструкция будет закодирована (с moffs32 из 0x12345678) просто в A1 78 56 34 12.

Однако, когда я запускаю это через дизассемблер, я получаю мусор:

# objdump -D -b binary -mi386 -Mx86-64 -Mintel file.bin
00000000 <.data>:
   0:   a1                      .byte 0xa1
   1:   78 56                   js     0x59
   3:   34 12                   xor    al,0x12

То же самое касается ndisasm:

# ndisasm -b 64 file.bin
00000000  A1                db 0xa1
00000001  7856              js 0x59
00000003  3412              xor al,0x12

Инструкцию я получу обратно только в том случае, если разберу ее для x86, а не x86-64 (ndisasm -b 32):
00000000 A178563412 mov eax,[0x12345678]

Почему это? В таблице указано, что инструкция все-таки действительна для 64бит.
Я чувствую, что мне не хватает чего-то фундаментального, но я не могу понять, что именно.

Обратите внимание, что moffs32 не означает 32-битное смещение. Это означает смещение к 32-битному операнду (соответствует eax). Также прочитайте указанную сноску № 3: «Операнды определяют простое смещение относительно базы сегмента, где 8, 16, 32 и 64 относятся к размеру данных. Атрибут размера адреса инструкции определяет размер смещение: 16, 32 или 64 бита».

Jester 04.06.2024 02:43

@Jester Я прочитал это предложение пару раз, но не совсем понял. Теперь становится очень понятно, почему он нормально дизассемблировался для x86 и почему в ответе пользователя 555045 всплывает переопределение размера адреса. Спасибо!

NyxCode 04.06.2024 02:53
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

32 в moffs32 описывает только размер операнда, а не размер адреса. Размер адреса по-прежнему составляет 64 бита по умолчанию в 64-битном режиме.

Таким образом, это справедливо в 64-битном режиме, но вам нужно больше байтов для смещения, например:

A1 78 56 34 12 00 00 00 00

Он по-прежнему кодирует mov eax, [0x12345678], но теперь в 64-битном режиме. Эта инструкция представляет собой редкий случай кодирования 64-битного постоянного адреса. Вы можете использовать его с 32-битным адресом с переопределением размера адреса:

67 A1 78 56 34 12

Но учтите, что это может быть медленнее из-за зависаний LCP на процессорах Intel, чем 7-байтовое кодирование с использованием обычного кода операции 8b 04 25 78 56 34 12 для mov reg, r/m с адресом в виде расширенного знаком disp32.

Очень интересно! Я неправильно прочитал таблицу или на связанной странице есть ошибка? Все ли инструкции с moffs, отличными от moffs64, требуют переопределения размера адреса?

NyxCode 04.06.2024 02:44

Я думаю, комментарий Джестера ответил на оба этих вопроса. Спасибо!

NyxCode 04.06.2024 02:55

Вы можете использовать его с 32-битным адресом с переопределением размера адреса: - но это может привести к зависанию LCP на процессорах Intel, если инструкция не поступает из кэша uop. Приводит ли префикс изменения длины (LCP) к остановке простой инструкции x86_64? (@NyxCode). Поэтому обычно, если вы хотите использовать 32-битный абсолютный адрес, который может поместиться в расширенный знаком disp32, используйте его вместо этого, даже если это требует дополнительного байта: 8b 04 25 78 56 34 12 используя обычный mov reg, r/m код операции, который не ограничивается rAX

Peter Cordes 06.06.2024 18:44

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