← SEARCHABLE ARCHIVE
Assembly · 2026-08-15

Comprender las banderas y los saltos condicionales de x86-64

CMP y TEST, condiciones con y sin signo y las decisiones del código sin ramas

INTERACTIVE READING MODE →

Comprender las banderas y los saltos condicionales de x86-64

Estos artículos del blog se han creado con fines didácticos. Los ejemplos usan sintaxis Intel. El rendimiento debe medirse en la CPU objetivo con la distribución real de entradas.

cmp eax, edx no guarda un resultado visible. ¿Cómo sabe el siguiente jl qué valor es menor? ¿Por qué los mismos bits 0xFFFFFFFF pueden ser -1 o 4.294.967.295? La respuesta está en RFLAGS y en la condición signed o unsigned que consume esas banderas.

Banderas habituales

BanderaSignificado
ZFel resultado fue cero
CFcarry/borrow unsigned
SFbit más alto del resultado
OFel resultado signed excedió su rango
PFparidad del byte inferior

Las comparaciones normales combinan sobre todo ZF, CF, SF y OF.

cmp y test

cmp rax, rdx

Conceptualmente calcula rax-rdx, descarta el valor y actualiza solo las banderas.

cmp eax, 10
je equal_ten
jl signed_less_than_ten

Un salto no está ligado gramaticalmente al cmp más cercano. Si una instrucción intermedia cambia las banderas, el salto observa el nuevo estado.

cmp eax, 10
add ecx, 1
jl somewhere      ; observa ADD

test funciona como un AND cuyo resultado se descarta; es común en pruebas de cero y máscaras.

test rax, rax
jz is_zero
test eax, 1
jnz is_odd

Igualdad y orden

La igualdad no depende del signo: je/jz prueba ZF=1 y jne/jnz prueba ZF=0. El orden sí debe separarse.

Significadosignedunsigned
left < rightjljb
left <= rightjlejbe
left > rightjgja
left >= rightjgejae
mov eax, 0FFFFFFFFh
cmp eax, 1
jl signed_less       ; -1 < 1, verdadero
jb unsigned_below    ; 4294967295 < 1, falso

El registro no lleva una etiqueta signed. La interpretación de las mismas banderas produce la diferencia.

CF y OF describen desbordamientos distintos

En ocho bits, 0xFF+1=0x00 tiene carry unsigned, pero signed -1+1 es correcto. 0x7F+1=0x80 es unsigned 128, pero excede el máximo signed 127.

add al, 1
jc unsigned_overflow
jo signed_overflow

C/C++ define la aritmética unsigned como módulo; el overflow signed es comportamiento indefinido. La existencia de OF no cambia el contrato del lenguaje. Además, inc y dec conservan CF, de modo que no son idénticos a add 1 y sub 1 para todas las banderas.

setcc y cmovcc

xor eax, eax
cmp edi, esi
setl al
ret

Convierte la comparación signed en 0 o 1. setcc solo escribe un byte, así que hay que limpiar conscientemente la parte superior.

cmp eax, edx
cmovl eax, edx

Un movimiento condicional selecciona sin bifurcar el control, pero puede alargar dependencias. No es automáticamente más rápido.

Branchless no significa más rápido

Las CPU modernas predicen saltos. Un jcc predecible es barato; con datos irregulares y caminos pequeños, setcc, cmovcc o máscaras pueden ayudar. Hay que medir distribución real, fallos de predicción, trabajo de ambos caminos, instrucciones y dependencias añadidas, y salida del compilador en la CPU objetivo.

Bucles y cortocircuito

xor eax, eax
xor edx, edx
loop_test:
    cmp rdx, rsi
    jae loop_done
    add eax, [rdi + rdx*4]
    inc rdx
    jmp loop_test
loop_done:
    ret

jae comprueba unsigned i >= count. La optimización puede rotar, desenrollar o vectorizar el bucle.

test rcx, rcx
jz done
cmp byte ptr [rcx + READY_OFFSET], 0
je done
call use
done:

Es una posible forma de p != nullptr && p->ready. El primer salto evita desreferenciar null; el orden forma parte de la seguridad.

Tabla de saltos

sub eax, 3
cmp eax, 4
ja default_case
jmp qword ptr [table + rax*8]

Tras normalizar los casos, una comprobación unsigned limita el índice antes del salto indirecto. Es también una frontera de seguridad importante.

No conservar flags a través de llamadas

cmp eax, edx
call helper
jl old_result       ; helper puede cambiar los flags

Convierta la condición en 0/1 antes de llamar o vuelva a comparar después.

Resumen

cmp y test producen banderas sin guardar su resultado. La igualdad usa ZF; el orden separa las condiciones signed SF/OF de las unsigned CF/ZF. Siga la última instrucción que definió las banderas, el signedness de la condición y el rango posible en cada arista de control.

Fuentes oficiales