assembly - rbp no permitido como base SIB?
x86 x86-64 (1)
Soy bastante nuevo en la codificación binaria x86-64. Estoy tratando de arreglar un viejo código "ensamblador".
De todos modos, estoy tratando de hacer algo como esto (sintaxis de Intel):
mov [rbp+rcx], al
El ensamblador está generando actualmente esto:
88 04 0D
pero eso no parece ser una instrucción válida.
Si cambio la base en el byte SIB de
rbp
a algún otro registro, funciona bien.
Otra forma de hacerlo funcionar es agregar un desplazamiento de un byte de cero (
88 44 0D 00
).
Esto parece suceder con otros códigos de operación similares.
¿Por qué no puedo usar
rbp
allí con
mod=00
?
La codificación que significaría que
rbp
es un código de escape para ningún registro base (solo un disp32 en SIB o relativo a RIP rel32 en ModRM).
La mayoría de los ensambladores ensamblan
[rbp]
en
[rbp + disp8=0]
.
Ya que no es necesario escalar, use
[rcx + rbp]
para evitar necesitar un disp8 = 0, porque
rbp
puede
ser un índice.
(SS y DS siempre son equivalentes en modo largo, por lo que no importa que base = RBP implique SS, mientras que base = RCX implica usar el segmento DS).
Modo de direccionamiento ModRM x86 / x86-64 que codifica casos especiales
(de una respuesta que escribí en ¿Por qué los rbp y rsp se denominan registros de propósito general? ). Esta pregunta parece ser el lugar perfecto para copiar o trasplantar esta sección.
rbp
/
r13
no puede ser un registro base sin desplazamiento
: esa codificación significa en cambio: (en ModRM)
rel32
(relativo a RIP), o (en SIB)
disp32
sin registro base.
(
r13
usa los mismos 3 bits en ModRM / SIB, por lo que esta opción simplifica la decodificación al no hacer que el decodificador de longitud de instrucción mire
el bit REX.B
para obtener el cuarto bit de registro de base).
[r13]
ensambla a
[r13 + disp8=0]
.
[r13+rdx]
ensambla a
[rdx+r13]
(evitando el problema intercambiando base / índice cuando esa es una opción).
rsp
/
r12
como registro base siempre necesita un byte SIB
.
(La codificación ModR / M de base = RSP es un código de escape para señalar un byte SIB, y nuevamente, más del decodificador tendría que preocuparse por el prefijo REX si
r12
se manejó de manera diferente).
rsp
no puede ser un registro de índice
.
Esto hace posible codificar
[rsp]
, que es más útil que
[rsp + rsp]
.
(Intel podría haber diseñado las codificaciones ModRM / SIB para los modos de direccionamiento de 32 bits (nuevo en 386), por lo que SIB sin índice solo era posible con base = ESP. Eso haría que
[eax + esp*4]
sea posible y solo excluir
[esp + esp*1/2/4/8]
. Pero eso no es útil, por lo que simplificaron el hardware al hacer que el índice = ESP sea el código sin índice independientemente de la base. Esto permite dos formas redundantes de codificar cualquier base o Modo de direccionamiento base + disp: con o sin un SIB.)
r12
puede
ser un registro de índice
.
A diferencia de los otros casos, esto no afecta la decodificación de longitud de instrucción.
Además, no se puede solucionar con una codificación más larga como en los otros casos.
AMD quería que el registro de AMD64 fuera lo más ortogonal posible, por lo que tiene sentido que gastarían unos cuantos transistores adicionales para verificar REX.X como parte de la decodificación índice / no índice.
Por ejemplo,
[rsp + r12*4]
requiere index = r12, por lo que tener
r12
no tiene un propósito general, haría de AMD64 un objetivo peor para el compilador.
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
Todo esto se aplica también a los modos de direccionamiento de 32 bits; la codificación es idéntica, excepto que no hay codificación relativa a EIP, solo dos formas redundantes de codificar disp32 sin base.
Consulte también https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2 para ver tablas como las del manual vol.2 de Intel.
Esto parece suceder con otros códigos de operación similares.
La codificación ModRM de los operandos r / m es siempre la misma. Algunos códigos de operación requieren un operando de registro y otros requieren memoria, pero el desplazamiento opcional opcional de ModRM + SIB + se corrige para que el mismo hardware pueda decodificarlo independientemente de la instrucción.
Hay algunos
mov al/ax/eax/rax, [qword absolute_address]
raros como
mov al/ax/eax/rax, [qword absolute_address]
que no usan la codificación ModRM para sus operandos, pero cualquiera que sí use el mismo formato.