← SEARCHABLE ARCHIVE
Assembly · 2026-08-15

Cómo leer registros e instrucciones x86-64

Desde registros parciales, tamaños de operando, MOV y LEA hasta la codificación máquina

INTERACTIVE READING MODE →

Cómo leer registros e instrucciones x86-64

Estos artículos del blog se han creado con fines didácticos. El código real puede variar según la generación de CPU, el sistema operativo, la ABI, el ensamblador, el compilador y las opciones de construcción; identifique siempre el entorno objetivo.

Al principio, rax, eax, ax y al parecen cuatro registros distintos. La habilidad importante no es memorizar todos los mnemónicos, sino seguir qué anchura se lee, de dónde viene el valor, dónde se escribe y qué estado de la máquina cambia.

Separar tres niveles

Expresión C       total += values[i];
Notación asm      add rax, qword ptr [rcx + rdx*8]
Bytes máquina     48 03 04 D1

C expresa tipos e intención; el ensamblador representa instrucciones y operandos de forma legible; el código máquina es la secuencia de bytes que decodifica la CPU. No existe una correspondencia obligatoria de una línea de fuente por una instrucción.

Registros generales y parciales

x86-64 ofrece 16 registros generales de 64 bits: rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp y r8–r15. Algunas funciones son arquitectónicas, como el uso de rsp por las instrucciones de pila. Los registros de argumentos los decide la ABI.

NombreParte accesible
raxlos 64 bits
eax32 bits inferiores
ax16 bits inferiores
al8 bits inferiores
ahbits 8–15, nombre histórico

En modo de 64 bits, escribir un registro general de 32 bits borra sus 32 bits superiores.

mov rax, 0FFFFFFFFFFFFFFFFh
mov eax, 7
; RAX = 0000000000000007h

Una escritura de 8 o 16 bits deja intactos los demás bits.

mov rax, 1122334455667788h
mov al, 0AAh
; RAX = 11223344556677AAh

Por eso el compilador puede poner xor eax, eax antes de setcc al. Los nombres ah, bh, ch y dh no pueden codificarse en una instrucción que necesita prefijo REX; normalmente conviene evitarlos en código nuevo.

La anchura forma parte del significado

mov al,  byte ptr  [rcx]    ; 1 byte
mov ax,  word ptr  [rcx]    ; 2 bytes
mov eax, dword ptr [rcx]    ; 4 bytes
mov rax, qword ptr [rcx]    ; 8 bytes

La dirección es la misma, pero cambia el tamaño del acceso. Una anchura equivocada puede leer o sobrescribir un campo vecino, cruzar una página o romper el contrato de layout de una estructura.

mov copia

Un mov normal no borra el origen. La mayoría de sus formas generales tampoco permiten copiar directamente de memoria a memoria.

mov rax, [rsi]
mov [rdi], rax

Esto no es una regla universal de que x86 solo pueda tocar una posición de memoria. Las instrucciones de cadena y las read-modify-write tienen sus propias formas; consulte la referencia de cada instrucción.

La extensión revela la interpretación entera

El byte 0xFF puede representar 255 sin signo o -1 con signo.

movzx eax, byte ptr [rcx]   ; 255
movsx eax, byte ptr [rcx]   ; extensión de signo a -1
movsxd rax, eax             ; signed de 32 a 64 bits

movzx rellena con ceros y movsx replica el bit de signo. El desensamblado no conserva los nombres de tipos C; extensión, comparación y salto son evidencias, no una reconstrucción perfecta.

lea calcula una dirección sin leer memoria

lea rax, [rcx + rdx*4 + 16]

rax recibe la dirección efectiva; no se lee el valor almacenado allí.

lea rax, [rcx + 8]          ; rax = rcx + 8
mov rax, [rcx + 8]          ; carga los 8 bytes almacenados
lea eax, [rcx + rcx*2]      ; eax = rcx * 3

Los compiladores también usan lea para sumas y multiplicaciones constantes que no modifican los flags aritméticos.

La aritmética sobrescribe el destino

add rax, rdx
sub rcx, 8
and eax, 0FFh
xor edx, edx       ; todo rdx queda en cero

En sintaxis Intel suele cumplirse destination = destination op source. Estas instrucciones también cambian los flags. Ante un jcc, setcc o cmovcc, encuentre la instrucción que realmente produjo el estado consumido.

Sintaxis Intel y AT&T

; Intel: destino primero
mov rax, qword ptr [rbx + 8]

# AT&T: origen primero
movq 8(%rbx), %rax

La operación de CPU es la misma, pero invertir los operandos invierte por completo el flujo de datos.

Longitud variable

Una instrucción x86-64 mide entre 1 y 15 bytes y puede contener prefijos, opcode, ModR/M, SIB, displacement e immediate.

48 89 D8                mov rax, rbx
B8 2A 00 00 00          mov eax, 42
48 8B 44 D1 10          mov rax, [rcx + rdx*8 + 16]

No es necesario memorizar bytes, pero la estructura importa al comprobar límites de instrucciones, parches, relocations o un desensamblador que empezó un byte tarde.

Seguir una función pequeña

Bajo System V, int transform(int x) { return x * 3 + 5; } puede compilarse así:

transform:
    lea eax, [rdi + rdi*2]
    add eax, 5
    ret

El argumento está en edi y el resultado en eax. El wraparound del hardware no define el overflow signed de C, que es comportamiento indefinido.

Lista de lectura

  1. ¿Sintaxis Intel o AT&T?
  2. ¿Qué anchura tienen los operandos?
  3. ¿Qué estado se lee y cuál se sobrescribe?
  4. ¿Una escritura de 32 bits limpia la mitad superior?
  5. ¿Cómo se calcula cada dirección efectiva?
  6. ¿Se producen o consumen flags?
  7. ¿La ABI asigna un rol de argumento, retorno o preservación?

Resumen

x86-64 se lee como transiciones de estado. Los registros parciales se solapan, una escritura de 32 bits limpia la mitad superior, mov copia, las extensiones muestran la interpretación entera y lea calcula una dirección efectiva sin acceder a memoria.

Fuentes oficiales