Buscar..


Saltos incondicionales

jmp a_label                      ;Jump to a_label
jmp bx                           ;Jump to address in BX
jmp WORD [aPointer]              ;Jump to address in aPointer
jmp 7c0h:0000h                   ;Jump to segment 7c0h and offset 0000h
jmp FAR WORD [aFarPointer]       ;Jump to segment:offset in aFarPointer

Relativo a saltos cercanos.

jmp a_label es:

  • cerca
    Solo especifica la parte de desplazamiento de la dirección lógica de destino. Se supone que el segmento es CS .
  • relativo
    La instrucción semántica es jump rel bytes adelante 1 de la siguiente dirección de instrucción o IP = IP + rel .

La instrucción se codifica como EB <rel8> o EB <rel16/32> , y el ensamblador toma la forma más adecuada, por lo general prefiere una más corta.
La anulación por ensamblador es posible, por ejemplo con NASM jmp SHORT a_label , jmp WORD a_label y jmp DWORD a_label generan las tres formas posibles.

Absolutos saltos indirectos cercanos.

jmp bx y jmp WORD [aPointer] son:

  • cerca
    Solo especifican la parte de desplazamiento de la dirección lógica de destino. Se supone que el segmento es CS .
  • absoluto indirecto
    La semántica de las instrucciones es saltar a la dirección en reg o mem o IP = reg , IP = mem .

La instrucción se codifica como FF /4 , para la memoria indirecta, el tamaño del operando se determina como para cualquier otro acceso a la memoria.

Saltos lejanos absolutos

jmp 7c0h:0000h es:

  • lejos
    Especifica ambas partes de la dirección lógica : el segmento y el desplazamiento.

  • absoluto La semántica de la instrucción es saltar al segmento de dirección : desplazamiento o CS = segment, IP = offset .

La instrucción se codifica como EA <imm32/48> según el tamaño del código.
Es posible elegir entre las dos formas en algún ensamblador, por ejemplo con NASM jmp 7c0h: WORD 0000h y jmp 7c0h: DWORD 0000h genera la primera y la segunda forma.

Saltos lejanos indirectos absolutos

jmp FAR WORD [aFarPointer] es:

  • Lejos Especifica ambas partes de la dirección lógica : el segmento y el desplazamiento.

  • Absoluto indirecto La semántica de la instrucción es saltar al segmento: desplazamiento almacenado en mem 2 o CS = mem[23:16/32], IP = [15/31:0] .

La instrucción se codifica como FF /5 , el tamaño del operando puede ser controlador con los especificadores de tamaño.
En NASM, un poco no intuitivo, son jmp FAR WORD [aFarPointer] para un operando 16:16 y jmp FAR DWORD [aFarPointer] para un operando 16:32 .


Saltos faltantes

  • casi absoluto
    Puede ser emulado con un salto casi indirecto.

      mov bx, target            ;BX = absolute address of target
      jmp bx
    
  • pariente lejano
    No tiene sentido o es demasiado estrecho de uso de todos modos.


1 Dos complementos se utilizan para especificar un desplazamiento firmado y, por lo tanto, saltar hacia atrás.
2, que puede ser un seg16: off16 o seg16: off32 , de tamaños 16:16 y 16:32 .

Condiciones de prueba

Para utilizar un salto condicional se debe probar una condición. La prueba de una condición aquí se refiere solo al acto de verificar las banderas, el salto real se describe en Saltos condicionales .

x86 prueba las condiciones basándose en el registro EFLAGS, que contiene un conjunto de indicadores que cada instrucción puede establecer potencialmente.

Las instrucciones aritméticas, como sub o add , y las instrucciones lógicas, como xor y and , obviamente, "establecen las banderas". Esto significa que las banderas CF , OF , SF , ZF , AF , PF son modificadas por esas instrucciones. Sin embargo, cualquier instrucción puede modificar los indicadores, por ejemplo, cmpxchg modifica la ZF .

Siempre revise la referencia de la instrucción para saber qué indicadores son modificados por una instrucción específica.

x86 tiene un conjunto de saltos condicionales , referidos anteriormente, que saltan si y solo si algunos indicadores están establecidos o algunos son claros o ambos.


Banderas

Las operaciones aritméticas y lógicas son muy útiles para establecer las banderas. Por ejemplo, después de un sub eax, ebx , que ahora tiene valores sin firmar , tenemos:

Bandera Cuando se establece Cuando claro
ZF Cuando el resultado es cero.
EAX - EBX = 0 ⇒ EAX = EBX
Cuando el resultado no es cero.
EAX - EBX ≠ 0 ⇒ EAX ≠ EBX
CF Cuando el resultado fue necesario llevar para el MSb.
EAX - EBX <0 ⇒ EAX <EBX
Cuando el resultado no fue necesario llevar para el MSb.
EAX - EBX ≮ 0 ⇒ EAX ≮ EBX
SF Cuando se establece el resultado MSb. Cuando el resultado MSb no se establece.
DE Cuando se produjo un desbordamiento firmado. Cuando no se produjo un desbordamiento firmado.
PF Cuando el número de bits establecido en el byte menos significativo del resultado es par. Cuando el número de bits establecido en el byte menos significativo del resultado es impar.
AF Cuando el dígito BCD inferior genera un carry.
Es bit 4 carry.
Cuando el dígito BCD inferior no generó un acarreo.
Es bit 4 carry.

Ensayos no destructivos.

El sub y and instrucciones que modifican su operando destino y requerirían dos copias adicionales (guardar y restaurar) para mantener el destino sin modificar.

Para realizar una prueba no destructiva hay las instrucciones cmp y test . Son idénticos a sus homólogos destructivos, excepto que el resultado de la operación se descarta y solo se guardan las banderas .

Destructivo No destructivo
sub cmp
and test

test eax, eax             ;and eax, eax
                          ;ZF = 1 iff EAX is zero

test eax, 03h             ;and eax, 03h
                          ;ZF = 1 if both bit[1:0] are clear
                          ;ZF = 0 if at least one of bit[1:0] is set

cmp eax, 241d             ;sub eax, 241d
                          ;ZF = 1 iff EAX is 241
                          ;CF = 1 iff EAX < 241

Pruebas firmadas y no firmadas.

La CPU no da un significado especial para registrar los valores 1 , signo es una construcción de programador. No hay diferencia cuando se prueban valores firmados y no firmados. El procesador calcula suficientes indicadores para probar las relaciones aritméticas habituales (igual, menor que, mayor que, etc.) tanto si los operandos se consideraran firmados como no firmados.


1 Aunque tiene algunas instrucciones que solo tienen sentido con formatos específicos, como el complemento de dos. Esto es para hacer que el código sea más eficiente, ya que la implementación del algoritmo en el software requeriría una gran cantidad de código.

Saltos condicionales

Según el estado de las banderas, la CPU puede ejecutar o ignorar un salto. Una instrucción que realiza un salto basado en las banderas cae bajo el nombre genérico de Jcc - Salta en el Código de condición 1 .

Sinónimos y terminología

Para mejorar la legibilidad del código de ensamblaje, Intel definió varios sinónimos para el mismo código de condición. Por ejemplo, jae , jnb y jnc tienen el mismo código de condición CF = 0 .

Si bien el nombre de la instrucción puede dar una idea muy clara de cuándo usarlo o no, el único enfoque significativo es reconocer los indicadores que deben probarse y luego elegir las instrucciones de manera adecuada.
Sin embargo, Intel dio los nombres de las instrucciones que tienen perfecto sentido cuando se usan después de una instrucción cmp . Para los propósitos de esta discusión, se asumirá que cmp ha establecido las banderas antes de un salto condicional.

Igualdad

El operando es igual si ZF se ha establecido, de lo contrario difieren. Para probar la igualdad necesitamos ZF = 1 .

je a_label           ;Jump if operands are equal
jz a_label           ;Jump if zero (Synonym)

jne a_label          ;Jump if operands are NOT equal
jnz a_label          ;Jump if not zero (Synonym)
Instrucción Banderas
je , jz ZF = 1
jne jnz ZF = 0

Mas grande que

Para los operandos sin firmar , el destino es mayor que el origen si no se necesita carry, es decir, si CF = 0 . Cuando CF = 0 es posible que los operandos fueran iguales, la prueba de ZF se desambiguará.

jae a_label      ;Jump if above or equal (>=)
jnc a_label      ;Jump if not carry (Synonym)
jnb a_label      ;Jump if not below (Synonym)

ja a_label       ;Jump if above  (>)
jnbe a_label     ;Jump if not below and not equal (Synonym)
Instrucción Banderas
jae , jnc , jnb CF = 0
ja , jnbe CF = 0, ZF = 0

Para los operandos firmados debemos verificar que SF = 0 , a menos que haya un desbordamiento firmado, en cuyo caso el SF resultante se invierte. Dado que OF = 0 si no se produjo un desbordamiento firmado y 1 de lo contrario, debemos verificar que SF = OF .

ZF se puede utilizar para implementar una prueba estricta / no estricta.

jge a_label      ;Jump if greater or equal (>=)
jnl a_label      ;Jump if not less (Synonym)

jg a_label       ;Jump if greater (>)
jnle a_label     ;Jump if not less and not equal (Synonym)
Instrucción Banderas
jge , jnl SF = OF
jg , jnle SF = OF, ZF = 0

Menos que

Estos utilizan las condiciones invertidas de arriba.

jbe a_label      ;Jump if below or equal (<=)
jna a_label      ;Jump if not above (Synonym)

jb a_label       ;Jump if below (<)
jc a_label       ;Jump if carry (Synonym)
jnae a_label     ;Jump if not above and not equal (Synonym)

;SIGNED 

jle a_label      ;Jump if less or equal (<=)
jng a_label      ;Jump if not greater (Synonym)

jl a_label       ;Jump if less (<)
jnge a_label     ;Jump if not greater and not equal (Synonym)
Instrucción Banderas
jbe jna CF = 1 o ZF = 1
jb jc jnae CF = 1
jle , jng SF! = OF o ZF = 1
jl , jnge SF! = OF

Banderas especificas

Cada bandera se puede probar individualmente con j<flag_name> donde nombre de bandera no contiene la F posterior (por ejemplo, CFC , PFP ).

Los códigos restantes no cubiertos antes son:

Instrucción Bandera
js SF = 1
jns SF = 0
jo OF = 1
jno OF = 0
jp , jpe (e = par) PF = 1
jnp , jpo (o = impar) PF = 0

Un salto más condicional (extra)

Un salto condicional especial x86 no prueba la bandera. En su lugar, prueba el valor del registro cx o ecx (basado en que el modo de dirección de la CPU actual es de 16 o 32 bits), y el salto se ejecuta cuando el registro contiene cero.

Esta instrucción fue diseñada para la validación del registro de contador ( cx/ecx ) antes de las instrucciones similares a las rep , o antes de loop bucles de loop .

jcxz  a_label   ; jump if cx (16b mode) or ecx (32b mode) is zero
jecxz a_label   ; synonym of jcxz (recommended in source code for 32b target)
Instrucción Registro (no bandera)
jcxz , jecxz cx = 0 (modo 16b)
jcxz , jecxz ecx = 0 (modo 32b)

1 O algo así.

Probar relaciones aritméticas

Enteros sin firmar

Mas grande que

cmp eax, ebx
ja a_label  

Mayor que o igual

cmp eax, ebx
jae a_label  

Menos que

cmp eax, ebx
jb a_label  

Menor o igual

cmp eax, ebx
jbe a_label 

Igual

cmp eax, ebx
je a_label 

No es igual

cmp eax, ebx
jne a_label     

Enteros firmados

Mas grande que

cmp eax, ebx
jg a_label  

Mayor que o igual

cmp eax, ebx
jge a_label  

Menos que

cmp eax, ebx
jl a_label  

Menor o igual

cmp eax, ebx
jle a_label 

Igual

cmp eax, ebx
je a_label 

No es igual

cmp eax, ebx
jne a_label 

a_label

En los ejemplos anteriores, a_label es el destino de destino para la CPU cuando la condición probada es "verdadera". Cuando la condición probada es "falsa", la CPU continuará en la siguiente instrucción después del salto condicional.

Sinónimos

Hay sinónimos de instrucciones que pueden usarse para mejorar la legibilidad del código.
Por ejemplo, ja y jnbe (Saltar no por debajo ni igual) son la misma instrucción.

Códigos de acompañante firmados y sin firmar.

Operación No firmado Firmado
> ja jg
> = jae jge
< jb jl
<= jbe jle
= je je
≠,! =, <> jne jne


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow