rbp не разрешен в качестве базы SIB?
Я совершенно новичок в двоичном кодировании x86-64. Я пытаюсь исправить старый код ассемблера.
В любом случае, я пытаюсь сделать что-то вроде этого (синтаксис Intel):
mov [rbp+rcx], al
Ассемблер в настоящее время генерирует это:
88 04 0D
но это не похоже на правильную инструкцию. Если я изменю базу в SIB-байте из rbp
в какой-то другой регистр он работает нормально. Еще один способ заставить его работать - добавить нулевое смещение в один байт (88 44 0D 00
). Похоже, это происходит с другими подобными кодами операций.
Почему я не могу использовать rbp
там с mod=00
?
1 ответ
Кодировка, которая будет означать rbp
является escape-кодом для отсутствия базового регистра (просто disp32 в SIB или RIP-относительный rel32 в ModRM). Большинство сборщиков собираются [rbp]
в [rbp + disp8=0]
,
Поскольку вам не нужно масштабировать, используйте [rcx + rbp]
вместо этого, чтобы избежать необходимости в disp8=0, потому что rbp
может быть индексом.
(SS и DS всегда эквивалентны в длинном режиме, поэтому не имеет значения, что base=RBP подразумевает SS, а base=RCX подразумевает использование сегмента DS.)
x86 / x86-64 ModRM режим адресации, кодирование особых случаев
(из ответа, который я написал на " Почему rbp и rsp называются регистрами общего назначения?"). Этот вопрос выглядит как идеальное место для копирования или трансплантации этого раздела.
rbp
/ r13
не может быть базовым регистром без смещения: вместо этого эта кодировка означает: (в ModRM) rel32
(Относительно RIP) или (в SIB) disp32
без базового регистра. (r13
использует те же 3 бита в ModRM/SIB, поэтому этот выбор упрощает декодирование, поскольку не позволяет декодеру длины команды смотреть на бит REX.B для получения 4-го бита базового регистра). [r13]
собирает в [r13 + disp8=0]
, [r13+rdx]
собирает в [rdx+r13]
(избежать проблемы путем замены базы / индекса, когда это возможно).
rsp
/ r12
в качестве базового регистра всегда нужен байт SIB. (Кодирование ModR/M base=RSP является escape-кодом для сигнализации байта SIB, и опять же, больше декодера должно заботиться о префиксе REX, если r12
был обработан по-другому).
rsp
не может быть индексным регистром. Это позволяет кодировать [rsp]
, что более полезно, чем [rsp + rsp]
, (Intel могла бы разработать кодировки ModRM / SIB для 32-битных режимов адресации (впервые в 386), поэтому SIB без индекса был возможен только при base=ESP. [eax + esp*4]
возможно и только исключает [esp + esp*1/2/4/8]
, Но это бесполезно, поэтому они упростили аппаратное обеспечение, сделав index=ESP кодом без индекса независимо от базы. Это позволяет использовать два избыточных способа кодирования любого режима адресации base или base+disp: с или без SIB.)
r12
может быть индексным регистром. В отличие от других случаев, это не влияет на декодирование длины команды. Кроме того, его нельзя обойти с помощью более длинной кодировки, как в других случаях. AMD хотела, чтобы регистр AMD64 был как можно более ортогональным, поэтому имеет смысл потратить несколько дополнительных транзисторов на проверку REX.X как часть декодирования индекса / без индекса. Например, [rsp + r12*4]
требует index=r12, поэтому имея r12
не вполне общее назначение сделало бы AMD64 худшей целью компилятора.
0: 41 8b 03 mov eax,DWORD PTR [r11]
3: 41 8b 04 24 mov eax,DWORD PTR [r12] # needs a SIB like RSP
7: 41 8b 45 00 mov eax,DWORD PTR [r13+0x0] # needs a disp8 like RBP
b: 41 8b 06 mov eax,DWORD PTR [r14]
e: 41 8b 07 mov eax,DWORD PTR [r15]
11: 43 8b 04 e3 mov eax,DWORD PTR [r11+r12*8] # *can* be an index
Все это относится и к 32-битным режимам адресации; кодировка идентична, за исключением того, что нет EIP-относительного кодирования, только два избыточных способа кодирования disp32 без основы.
См. Также https://wiki.osdev.org/X86-64_Instruction_Encoding для таблиц, подобных таблицам в руководстве Intel vol.2.
Похоже, это происходит с другими подобными кодами операций.
Кодирование ModRM операндов r/m всегда одинаково. Некоторые коды операций требуют операнда регистра, а некоторые требуют памяти, но фактическое ModRM + необязательное смещение SIB + исправлено, поэтому одно и то же оборудование может декодировать его независимо от инструкции.
Есть несколько редких кодов операций, таких как mov al/ax/eax/rax, [qword absolute_address]
которые вообще не используют кодирование ModRM для своих операндов, но те, которые используют тот же формат.