Кодировка, которая будет означать rbp
, является управляющим кодом без базового регистра (просто 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#32.2F64-bit_addressing_2 для таблиц, подобных таблицам в Intel vol.2manual.
Похоже, что это происходит с другими подобными кодами операций.
Кодирование ModRM операндов r / m всегда одинаково.Некоторые коды операций требуют операнда регистра, а некоторые требуют памяти, но фактическое ModRM + необязательное смещение SIB + исправлено, поэтому одно и то же оборудование может декодировать его независимо от инструкции.
Существует несколько редких кодов операций, таких как mov al/ax/eax/rax, [qword absolute_address]
, которые вообще не используют кодирование ModRM для своих операндов, но все, которые используют тот же формат.