CALL

Procedimiento de llamada

estableVMJITAOTinstruccion

Codificaciones

OpcodeInstruccionOp/En64 bitsCompat/LegacyDescripcion
E8 cwCALL rel16DNo soportadoValidoCall near, relative, displacement relative to next instruction.
E8 cdCALL rel32DValidoValidoCall near, relative, displacement relative to next instruction. 32-bit displacement sign extended to 64-bits in 64-bit mode.
FF /2CALL r/m16MNo codificableValidoCall near, absolute indirect, address given in r/m16.
FF /2CALL r/m32MNo codificableValidoCall near, absolute indirect, address given in r/m32.
FF /2CALL r/m64MValidoNo codificableCall near, absolute indirect, address given in r/m64.
9A cdCALL ptr16:16DNo validoValidoLlame lejos, absoluto, dirección dada en operando.
9A cpCALL ptr16:32DNo validoValidoLlame lejos, absoluto, dirección dada en operando.
FF /3CALL m16:16MValidoValidoCall far, dirección indirecta absoluta dada en m16:16. En modo 32-bit: si el selector apunta a una puerta, entonces RIP = 32-bit cero desplazamiento extendido tomado de la puerta; de lo contrario RIP = cero extendido 16-bit offset desde el puntero lejano referenciado en la instrucción.
FF /3CALL m16:32MValidoValidoEn modo 64-bit: Si el selector apunta a una puerta, entonces RIP = 64-bit desplazamiento tomado de la puerta; de lo contrario RIP = cero extendido 32-bit offset de distancia puntero referenciado en la instrucción.
REX.W FF /3CALL m16:64MValidoNo codificableIn 64-bit mode: If selector points to a gate, then RIP = 64-bit displacement taken from gate; else RIP = 64-bit offset from far pointer referenced in the instruction.

Codificacion de operandos

Cada modo es un valor de la columna Op/En de arriba. Dice en que campo de la instruccion codificada va cada operando, en el orden en que se escriben, y si la instruccion lo lee, lo escribe o ambas cosas.

D

  1. offsetdesplazamiento que sigue al opcode

M

  1. modrm.rm lecturabyte ModRM, campo r/m (bits 2-0); con el byte SIB y el desplazamiento cuando el campo mod los pide

Coste medido

Sin medir: no se ejecuta en procesadores de 64 bits.

Descripción

Guarda el procedimiento que une la información sobre la pila y las ramas al procedimiento llamado especificado utilizando el objetivo operando. El objetivo operando especifica la dirección de la primera instrucción en el procedimiento llamado. El operando puede ser un valor inmediato, un registro de proposito general, o una ubicación de memoria.

Esta instrucción se puede utilizar para ejecutar cuatro tipos de llamadas:

registro), a veces referido como una llamada intrasede.

se refiere a una llamada intersegmentaria.

del actual programa o procedimiento de ejecución.

Estos últimos dos tipos de llamadas (llamadas de nivel intermedio y conmutador de tareas) sólo pueden ejecutarse en modo protegido. Ver "Procedimientos de llamada usando Call y RET" en el capítulo 6 de Intel(R) 64 e IA-32 Architectures Software Developer's Manual, Volumen 1, para obtener información adicional sobre llamadas cercanas, lejanas y de nivel intermedio. Vea el capítulo 10, "Manejo de clics", en el Manual de Software de Arquitecturas Intel(R) 64 e IA-32, Volumen 3A, para obtener información sobre el desempeño de los conmutadores de tareas con la instrucción CALL.

Cerca de Call. Al ejecutar una llamada cercana, el procesador empuja el valor del registro EIP (que contiene la compensación de la instrucción después de la instrucción CALL) en la pila (para uso posterior como un retorno-puntero de instruccion). El procesador luego se ramifica a la dirección en el segmento de código actual especificado por el objetivo operando. El objetivo operando especifica una compensación absoluta en el segmento de código (una compensación de la base del segmento de código) o una compensación relativa (un desplazamiento firmado en relación con el valor actual del puntero de instruccion en el registro EIP; este valor apunta a la instrucción siguiendo la instrucción CALL). El registro CS no se cambia en llamadas cercanas.

Para un llamado cercano absoluto, un offset absoluto se especifica indirectamente en un registro de proposito general o una ubicación de memoria (r/m16, r/m32, o r/m64). El atributo el operando-size determina el tamaño del objetivo operando (16, 32 o 64 bits). Cuando en el modo 64-bit, el tamaño de operando para llamada cercana (y todas las ramas cercanas) se ve obligado a 64-bits. Los offsets absolutos se cargan directamente en el registro EIP(RIP). Si el atributo el tamaño de operando es 16, los dos bytes superiores del registro EIP se limpian, dando como resultado un tamaño máximo puntero de instruccion de 16 bits. Al acceder a un offset absoluto indirectamente utilizando el puntero de pila [ESP] como registro base, el valor base utilizado es el valor del ESP antes de ejecutar la instrucción.

Un offset relativo (rel16 o rel32) se especifica generalmente como una etiqueta en código de montaje. Pero a nivel de código de máquina, se codifica como un valor inmediato firmado de 16 o 32 bits. Este valor se añade al valor del registro EIP(RIP). En el modo 64-bit el offset relativo es siempre un valor inmediato de 32-bit que se muestra extendido a 64-bits antes de que se añada al valor en el registro RIP para el cálculo objetivo. Como con compensaciones absolutas, el atributo el operando-size determina el tamaño del objetivo operando (16, 32 o 64 bits). En el modo 64-bit el objetivo operando siempre será de 64-bits porque el tamaño de operando es forzado a 64-bits para ramas cercanas.

Far Calls in Real-Address or modo virtual-8086. Al ejecutar una llamada de lejos en realaddress o modo virtual-8086, el procesador empuja el valor actual de los registros CS y EIP en la pila para su uso como un retorno-puntero de instruccion. A continuación, el procesador realiza una "direccional rama" al segmento de código y se compensa con el objetivo operando para el procedimiento llamado. El objetivo operando especifica una dirección absoluta directa con un puntero (ptr16:16 o ptr16:32) o indirectamente con una ubicación de memoria (m16:16 o m16:32). Con el método puntero, el segmento y la compensación del procedimiento llamado se codifica en la instrucción utilizando una dirección de 4 bytes (16-bit tamaño de operando) o 6-byte (32-bit tamaño de operando) de distancia inmediata. Con el método indirecto, el objetivo operando especifica una ubicación de memoria que contiene una dirección de 4 bytes (16-bit tamaño de operando) o 6-byte (32-bit tamaño de operando). El atributo el operando-size determina el tamaño del offset (16 o 32 bits) en la dirección remota. La dirección está cargada directamente en los registros CS y EIP. Si el atributo el operando-size es 16, los dos bytes superiores del registro EIP se limpian.

Far Calls en modo protegido. Cuando el procesador está operando en modo protegido, la instrucción CALL se puede utilizar para realizar los siguientes tipos de llamadas:

En modo protegido, el procesador siempre utiliza la parte el selector de segmento de la dirección remota para acceder al descriptor correspondiente en el GDT o LDT. El tipo de descriptor (segmento de código, puerta de llamada, puerta de tarea, o TSS) y los derechos de acceso determinan el tipo de operación de llamada a realizar.

Si el descriptor seleccionado es para un segmento de código, se realiza una llamada a un segmento de código al mismo nivel de privilegios. (Si el segmento de código seleccionado está a un nivel de privilegios diferente y el segmento de código no está conformando, se genera una excepción de protección general.) Una llamada al mismo nivel de privilegios en modo protegido es muy similar a la realizada en dirección real o modo virtual-8086. El objetivo operando especifica una dirección absoluta directa con un puntero (ptr16:16 o ptr16:32) o indirectamente con una ubicación de memoria (m16:16 o m16:32). El atributo operandsize determina el tamaño del offset (16 o 32 bits) en la dirección remota. El nuevo código selector de segmento y su descriptor se cargan en el registro CS; el offset de la instrucción se carga en el registro EIP.

Una puerta de llamada (descrita en el párrafo siguiente) también puede utilizarse para realizar una llamada a un segmento de código al mismo nivel de privilegios. El uso de este mecanismo proporciona un nivel adicional de indirectidad y es el método preferido de hacer llamadas entre segmentos de código de 16 bits y 32 bits.

Al ejecutar una llamada inter-privilege-level far, el segmento de código para el procedimiento que se llama debe ser accedido a través de una puerta de llamada. El selector de segmento especificado por el objetivo operando identifica la puerta de llamada. El objetivo operando puede especificar la puerta de llamada selector de segmento directamente con un puntero (ptr16:16 o ptr16:32) o indirectamente con una ubicación de memoria (m16:16 o m16:32). El procesador obtiene el selector de segmento para el nuevo segmento de código y el nuevo puntero de instruccion (offset) del descriptor de la puerta de llamada. (El offset del objetivo operando es ignorado cuando se utiliza una puerta de llamada).

En las llamadas inter-privilege-level, el procesador cambia a la pila para el nivel de privilegio del procedimiento llamado. El selector de segmento para el nuevo segmento de pila se especifica en el TSS para la tarea actualmente en ejecución. La rama al nuevo segmento de código se produce después del interruptor de la pila. (Nota que cuando se utiliza una puerta de llamada para realizar una llamada a un segmento al mismo nivel de privilegios, no se produce ningún interruptor de pila.) En la nueva pila, el procesador empuja el selector de segmento y puntero de pila para la pila del procedimiento de llamada, un conjunto opcional de parámetros de la pila de procedimientos de llamada, y el selector de segmento y puntero de instruccion para el segmento de código del procedimiento de llamada. (Un valor en el descriptor de la puerta de llamada determina cuántos parámetros para copiar a la nueva pila.) Finalmente, las ramas del procesador a la dirección del procedimiento que se llama dentro del nuevo segmento de código.

Ejecutar un interruptor de tarea con la instrucción CALL es similar a ejecutar una llamada a través de una puerta de llamada. El objetivo operando especifica el selector de segmento de la puerta de tarea para la nueva tarea activada por el interruptor (el offset en el objetivo operando es ignorado). La puerta de tarea a su vez apunta al TSS para la nueva tarea, que contiene los selectores de segmentos para los segmentos de código y pila de la tarea. Tenga en cuenta que el TSS también contiene el valor EIP para la siguiente instrucción que debía ejecutarse antes de que se suspendiera la tarea de llamada. Este valor puntero de instruccion se carga en el registro EIP para volver a iniciar la tarea de llamada.

La instrucción CALL también puede especificar el selector de segmento del TSS directamente, que elimina la indirecta de la puerta de tarea. Ver Capítulo 10, "Manejo de Pulsar", en el Intel(R) 64 e IA-32 Architectures Software Developer's Manual, Volumen 3A, para obtener información sobre la mecánica de un interruptor de tarea.

Cuando la ejecución de una instrucción CALL afecta a un interruptor de tarea, la bandera de tarea anidada (NT) se establece en el registro EFLAGS y el nuevo campo de enlace de tareas anterior de TSS se carga con el selector TSS de la antigua tarea. Se espera que el código suspenda esta tarea anidada ejecutando una instrucción IRET que, debido a que se establece la bandera NT, utiliza automáticamente el enlace de tarea anterior para volver a la tarea de llamada. (Ver "Task Linking" en el capítulo 10 de Intel(R) 64 e IA-32 Architectures Software Developer's Manual, Volumen 3A, para información sobre tareas anidadas.) Las tareas de conmutación con la instrucción CALL difieren a este respecto de la instrucción JMP. JMP no establece la bandera NT y por lo tanto no espera que una instrucción IRET suspenda la tarea.

Mixing 16-Bit y 32-Bit Calls. Al hacer llamadas de lejos entre segmentos de código de 16 bits y 32 bits, utilice una puerta de llamada. Si la llamada es de un segmento de código de 32 bits a un segmento de código de 16 bits, la llamada debe hacerse de los primeros 64 KBytes del segmento de código de 32 bits. Esto se debe a que el operando-size atributo de la instrucción se establece a 16, por lo que sólo se puede guardar una dirección de retorno de 16 bits. Además, la llamada debe hacerse usando una puerta de llamada de 16 bits para que los valores de 16 bits puedan ser empujados en la pila. Ver capítulo 24, "Mixing 16-Bit and 32-Bit Code", en el Intel(R) 64 e IA-32 Architectures Software Developer's Manual, Volumen 3B, para más información.

Far Calls in Compatibility Mode. Cuando el procesador está operando en modo de compatibilidad, la instrucción CALL se puede utilizar para realizar los siguientes tipos de llamadas:

Tenga en cuenta que una instrucción CALL no se puede utilizar para causar un interruptor de tarea en modo de compatibilidad ya que los conmutadores de tarea no son compatibles en modo IA-32e.

En modo de compatibilidad, el procesador siempre utiliza la parte el selector de segmento de la dirección remota para acceder al descriptor correspondiente en el GDT o LDT. El tipo de descriptor (segmento de código, puerta de llamada) y los derechos de acceso determinan el tipo de operación de llamada a realizar.

Si el descriptor seleccionado es para un segmento de código, se realiza una llamada a un segmento de código al mismo nivel de privilegios. (Si el segmento de código seleccionado está a un nivel de privilegio diferente y el segmento de código no está conformando, se genera una excepción de protección general.) Una llamada al mismo nivel de privilegios en modo de compatibilidad es muy similar a la realizada en modo protegido. El objetivo operando especifica una dirección absoluta directa con un puntero (ptr16:16 o ptr16:32) o indirectamente con una ubicación de memoria (m16:16 o m16:32). El atributo el operando-size determina el tamaño del offset (16 o 32 bits) en la dirección remota. El nuevo código selector de segmento y su descriptor se cargan en el registro CS y el offset de la instrucción se carga en el registro EIP. La diferencia es que el modo 64-bit puede ser introducido. Esto especificado por el bit L en el nuevo descriptor del segmento de código.

Tenga en cuenta que una puerta de llamada de 64 bits (descrita en el párrafo siguiente) también se puede utilizar para realizar una llamada a un segmento de código al mismo nivel de privilegios. Sin embargo, el uso de este mecanismo requiere que el descriptor de segmento de código objetivo tenga el conjunto de bits L, causando una entrada al modo 64-bit.

Al ejecutar una llamada interprivilege-level far, el segmento de código para el procedimiento que se llama debe ser accedido a través de una puerta de llamada de 64 bits. El selector de segmento especificado por el objetivo operando identifica la puerta de llamada. El objetivo

operando puede especificar la puerta de llamada selector de segmento directamente con un puntero (ptr16:16 o ptr16:32) o indirectamente con una ubicación de memoria (m16:16 o m16:32). El procesador obtiene el selector de segmento para el nuevo segmento de código y el nuevo puntero de instruccion (offset) del descriptor de puerta de llamada de 16 bytes. (El offset del objetivo operando es ignorado cuando se utiliza una puerta de llamada).

En las llamadas inter-privilege-level, el procesador cambia a la pila para el nivel de privilegio del procedimiento llamado. El selector de segmento para el nuevo segmento de pila se establece en NULL. El nuevo puntero de pila se especifica en el TSS para la tarea en curso. La rama al nuevo segmento de código se produce después del interruptor de la pila. (Nota que cuando se utiliza una puerta de llamada para realizar una llamada a un segmento al mismo nivel de privilegios, un interruptor de pila implícita ocurre como resultado de entrar en modo de 64 bits. El selector SS no cambia, pero los accesos de segmento de pila utilizan una base de segmento de 0x0, se ignora el límite, y el tamaño de pila predeterminado es de 64 bits. El valor total de RSP se utiliza para el offset, del cual el quedan indefinidas superior de 32 bits) En la nueva pila, el procesador empuja el selector de segmento y puntero de pila para la pila del procedimiento de llamada y el selector de segmento y puntero de instruccion para el segmento de código del procedimiento de llamada. (La copia del parámetro no se admite en modo IA-32e.) Por último, el procesador se ramifica a la dirección del procedimiento que se llama dentro del nuevo segmento de código.

Cerca/(Far) Llama en modo de 64 bits. Cuando el procesador está operando en modo de 64 bits, la instrucción CALL se puede utilizar para realizar los siguientes tipos de llamadas:

Tenga en cuenta que en este modo la instrucción CALL no se puede utilizar para causar un interruptor de tarea en modo de 64 bits ya que los conmutadores de tarea no son compatibles en modo IA-32e.

En modo de 64 bits, el procesador siempre utiliza la parte el selector de segmento de la dirección remota para acceder al descriptor correspondiente en el GDT o LDT. El tipo de descriptor (segmento de código, puerta de llamada) y los derechos de acceso determinan el tipo de operación de llamada a realizar.

Si el descriptor seleccionado es para un segmento de código, se realiza una llamada a un segmento de código al mismo nivel de privilegios. (Si el segmento de código seleccionado está a un nivel de privilegios diferente y el segmento de código no está conformando, se genera una excepción de protección general.) Una llamada al mismo nivel de privilegios en modo de 64 bits es muy similar a la realizada en modo de compatibilidad. El objetivo operando especifica una dirección absoluta indirectamente con una ubicación de memoria (m16:16, m16:32 o m16:64). La forma de CALL con una especificación directa de dirección absoluta no se define en modo de 64 bits. El atributo el operando-size determina el tamaño del offset (16, 32 o 64 bits) en la dirección remota. El nuevo código selector de segmento y su descriptor se cargan en el registro CS; el offset de la instrucción se carga en el registro EIP. El nuevo segmento de código puede especificar la entrada en modo compatible o de 64 bits, basado en el valor de bit L.

Una puerta de llamada de 64 bits (descrita en el párrafo siguiente) también puede utilizarse para realizar una llamada a un segmento de código al mismo nivel de privilegios. Sin embargo, el uso de este mecanismo requiere que el descriptor de segmento de código objetivo tenga el conjunto de bits L.

Al ejecutar una llamada interprivilege-level far, el segmento de código para el procedimiento que se llama debe ser accedido a través de una puerta de llamada de 64 bits. El selector de segmento especificado por el objetivo operando identifica la puerta de llamada. El objetivo operando sólo puede especificar la puerta de llamada selector de segmento indirectamente con una ubicación de memoria (m16:16, m16:32 o m16:64). El procesador obtiene el selector de segmento para el nuevo segmento de código y el nuevo puntero de instruccion (offset) del descriptor de puerta de llamada de 16 bytes. (El offset del objetivo operando es ignorado cuando se utiliza una puerta de llamada).

En las llamadas inter-privilege-level, el procesador cambia a la pila para el nivel de privilegio del procedimiento llamado. El selector de segmento para el nuevo segmento de pila se establece en NULL. El nuevo puntero de pila se especifica en el TSS para la tarea en curso. La rama al nuevo segmento de código se produce después del interruptor de la pila.

Tenga en cuenta que al utilizar una puerta de llamada para realizar una llamada a un segmento al mismo nivel de privilegios, un interruptor de pila implícita ocurre como resultado de entrar en modo 64-bit. El selector SS no cambia, pero los accesos de segmento de pila utilizan una base de segmento de 0x0, se ignora el límite, y el tamaño de pila predeterminado es de 64 bits. (El valor total de RSP se utiliza para el offset.) En la nueva pila, el procesador empuja el selector de segmento y puntero de pila para la pila del procedimiento de llamada y el selector de segmento y puntero de instruccion para el segmento de código del procedimiento de llamada. (La copia del parámetro no se admite en modo IA-32e.) Por último, el procesador se ramifica a la dirección del procedimiento que se llama dentro del nuevo segmento de código.

Consulte el Capítulo 6, "Procedimientos, Interrupciones y Excepciones", y el Capítulo 18, "Control-flow Enforcement Technology (CET)," en el Intel(R) 64 e IA-32 Architectures Software Developer's Manual, Volumen 1, para CET

details.

Cuando las transiciones FRED están habilitadas, una ejecución de CALL lejano que hace referencia a una puerta de llamada causa un general-protec-

excepción tion, al igual que una ejecución de lejos CALL que entraría en modo compatibilidad cuando CPL es 0.

Ordenación de instrucciones. Las instrucciones después de una llamada lejana pueden ser arrebatadas de memoria antes de instrucciones anteriores

ejecución completa, pero no ejecutarán (incluso especulativamente) hasta que todas las instrucciones antes de la llamada de lejos tengan

ejecución completada (las instrucciones posteriores pueden ejecutarse antes de que los datos almacenados por las instrucciones anteriores tengan

ser mundialmente visible).

Las instrucciones secuencialmente después de una instrucción casi indirecta CALL (es decir, las que no están en el objetivo) pueden ejecutarse

especulativamente. Si el software necesita prevenir esto (por ejemplo, para prevenir un canal lateral de ejecución especulativa),

entonces una instrucción LFENCE código de operación se puede colocar después del CALL indirecto cercano para bloquear la ejecución especulativa

tion.

Operación

IF near call
    THEN IF near relative call
          THEN
               IF OperandSize = 64
                      THEN
                            tempDEST := SignExtend(DEST); (* DEST is rel32 *)
                            tempRIP := RIP + tempDEST;
                            IF stack not large enough for a 8-byte return address
                                  THEN #SS(0); FI;
                            Push(RIP);
                            IF ShadowStackEnabled(CPL) AND DEST != 0
                                  ShadowStackPush8B(RIP);
                            FI;
                            RIP := tempRIP;
                FI;
               IF OperandSize = 32
                      THEN
                            tempEIP := EIP + DEST; (* DEST is rel32 *)
                            IF tempEIP is not within code segment limit THEN #GP(0); FI;
                            IF stack not large enough for a 4-byte return address
                                  THEN #SS(0); FI;
                            Push(EIP);
                            IF ShadowStackEnabled(CPL) AND DEST != 0
                                  ShadowStackPush4B(EIP);
                            FI;
                            EIP := tempEIP;
                FI;
                IF OperandSize = 16
                      THEN
                            tempEIP := (EIP + DEST) AND 0000FFFFH; (* DEST is rel16 *)
                            IF tempEIP is not within code segment limit THEN #GP(0); FI;
                            IF stack not large enough for a 2-byte return address
                                  THEN #SS(0); FI;
                            Push(IP);
                            IF ShadowStackEnabled(CPL) AND DEST != 0
                                  (* IP is zero extended and pushed as a 32 bit value on shadow stack *)
                                  ShadowStackPush4B(IP);
                            FI;


                             EIP := tempEIP;
                FI;
          ELSE (* Near absolute call *)
               IF OperandSize = 64

                       THEN
                             tempRIP := DEST; (* DEST is r/m64 *)
                             IF stack not large enough for a 8-byte return address
                                   THEN #SS(0); FI;
                             Push(RIP);
                             IF ShadowStackEnabled(CPL)
                                   ShadowStackPush8B(RIP);
                             FI;
                             RIP := tempRIP;

                FI;
               IF OperandSize = 32

                       THEN
                             tempEIP := DEST; (* DEST is r/m32 *)
                             IF tempEIP is not within code segment limit THEN #GP(0); FI;
                             IF stack not large enough for a 4-byte return address
                                   THEN #SS(0); FI;
                             Push(EIP);
                             IF ShadowStackEnabled(CPL)
                                   ShadowStackPush4B(EIP);
                             FI;
                             EIP := tempEIP;

                FI;
               IF OperandSize = 16

                       THEN
                             tempEIP := DEST AND 0000FFFFH; (* DEST is r/m16 *)
                             IF tempEIP is not within code segment limit THEN #GP(0); FI;
                             IF stack not large enough for a 2-byte return address
                                   THEN #SS(0); FI;
                             Push(IP);
                             IF ShadowStackEnabled(CPL)
                                   (* IP is zero extended and pushed as a 32 bit value on shadow stack *)
                                   ShadowStackPush4B(IP);
                             FI;
                             EIP := tempEIP;

                FI;
    FI;rel/abs
    IF (Call near indirect, absolute indirect)

          IF EndbranchEnabledAndNotSuppressed(CPL)
                IF CPL = 3
                       THEN
                             IF ( no 3EH prefix OR IA32_U_CET.NO_TRACK_EN == 0 )
                                   THEN
                                         IA32_U_CET.TRACKER = WAIT_FOR_ENDBRANCH
                             FI;
                       ELSE
                             IF ( no 3EH prefix OR IA32_S_CET.NO_TRACK_EN == 0 )
                                   THEN
                                         IA32_S_CET.TRACKER = WAIT_FOR_ENDBRANCH
                             FI;
                FI;


          FI;
    FI;
FI; near

IF far call and (PE = 0 or (PE = 1 and VM = 1)) (* Real-address or virtual-8086 mode *)
    THEN
         IF OperandSize = 32
                THEN
                       IF stack not large enough for a 6-byte return address
                             THEN #SS(0); FI;
                       IF DEST[31:16] is not zero THEN #GP(0); FI;
                       Push(CS); (* Padded with 16 high-order bits *)
                       Push(EIP);
                       CS := DEST[47:32]; (* DEST is ptr16:32 or [m16:32] *)
                       EIP := DEST[31:0]; (* DEST is ptr16:32 or [m16:32] *)
               ELSE (* OperandSize = 16 *)
                       IF stack not large enough for a 4-byte return address
                             THEN #SS(0); FI;
                       Push(CS);
                       Push(IP);
                       CS := DEST[31:16]; (* DEST is ptr16:16 or [m16:16] *)
                       EIP := DEST[15:0]; (* DEST is ptr16:16 or [m16:16]; clear upper 16 bits *)
          FI;

FI;

IF far call and (PE = 1 and VM = 0) (* Protected mode or IA-32e Mode, not virtual-8086 mode*)
    THEN
          IF segment selector in target operand NULL
                THEN #GP(0); FI;
          IF segment selector index not within descriptor table limits
                THEN #GP(new code segment selector); FI;
          Read type and access rights of selected segment descriptor;
          IF IA32_EFER.LMA = 0
                THEN
                       IF segment type is not a conforming or nonconforming code segment, call gate, task gate, or TSS
                             THEN #GP(segment selector); FI;
                ELSE
                       IF segment type is not a conforming or nonconforming code segment or 64-bit call gate
                             THEN #GP(segment selector); FI;
          FI;
          Depending on type and access rights:
                GO TO CONFORMING-CODE-SEGMENT;
                GO TO NONCONFORMING-CODE-SEGMENT;
                GO TO CALL-GATE;
                GO TO TASK-GATE;
                GO TO TASK-STATE-SEGMENT;

FI;

CONFORMING-CODE-SEGMENT:
    IF L bit = 1 and D bit = 1 and IA32_EFER.LMA = 1
          THEN GP(new code segment selector); FI;
    IF DPL > CPL
          THEN #GP(new code segment selector); FI;
    IF CR4.FRED = 1 and CPL = 0 and L bit = 0


          THEN GP(new code segment selector); FI;
    IF segment not present

          THEN #NP(new code segment selector); FI;
    IF stack not large enough for return address

          THEN #SS(0); FI;
    tempEIP := DEST(Offset);
    IF target mode = Compatibility mode

          THEN tempEIP := tempEIP AND 00000000_FFFFFFFFH; FI;
    IF OperandSize = 16

          THEN
                tempEIP := tempEIP AND 0000FFFFH; FI; (* Clear upper 16 bits *)

    IF (IA32_EFER.LMA = 0 or target mode = Compatibility mode) and (tempEIP outside new code segment limit)
          THEN #GP(0); FI;

    IF tempEIP is non-canonical
          THEN #GP(0); FI;

    IF ShadowStackEnabled(CPL)
          IF OperandSize = 32
                THEN
                       tempPushLIP = CSBASE + EIP;
                ELSE
                       IF OperandSize = 16
                             THEN
                                   tempPushLIP = CSBASE + IP;
                             ELSE (* OperandSize = 64 *)
                                   tempPushLIP = RIP;
                       FI;
          FI;
          tempPushCS = CS;

    FI;
    IF OperandSize = 32

          THEN
                Push(CS); (* Padded with 16 high-order bits *)
                Push(EIP);
                CS := DEST(CodeSegmentSelector);
                (* Segment descriptor information also loaded *)
                CS(RPL) := CPL;
                EIP := tempEIP;

          ELSE
               IF OperandSize = 16
                       THEN
                             Push(CS);
                             Push(IP);
                             CS := DEST(CodeSegmentSelector);
                             (* Segment descriptor information also loaded *)
                             CS(RPL) := CPL;
                             EIP := tempEIP;
                    ELSE (* OperandSize = 64 *)
                             Push(CS); (* Padded with 48 high-order bits *)
                             Push(RIP);
                             CS := DEST(CodeSegmentSelector);
                             (* Segment descriptor information also loaded *)
                             CS(RPL) := CPL;
                             RIP := tempEIP;
                FI;


    FI;
    IF ShadowStackEnabled(CPL)

          IF (IA32_EFER.LMA and DEST(CodeSegmentSelector).L) = 0
                (* If target is legacy or compatibility mode then the SSP must be in low 4GB *)
                IF (SSP & 0xFFFFFFFF00000000 != 0)
                       THEN #GP(0); FI;

          FI;
          (* align to 8 byte boundary if not already aligned *)
          tempSSP = SSP;
          Shadow_stack_store 4 bytes of 0 to (SSP  4)
          SSP = SSP & 0xFFFFFFFFFFFFFFF8H
          ShadowStackPush8B(tempPushCS); (* Padded with 48 high-order bits of 0 *)
          ShadowStackPush8B(tempPushLIP); (* Padded with 32 high-order bits of 0 for 32 bit LIP*)
          ShadowStackPush8B(tempSSP);
    FI;
    IF EndbranchEnabled(CPL)
          IF CPL = 3

                THEN
                       IA32_U_CET.TRACKER = WAIT_FOR_ENDBRANCH
                       IA32_U_CET.SUPPRESS = 0

                ELSE
                       IA32_S_CET.TRACKER = WAIT_FOR_ENDBRANCH
                       IA32_S_CET.SUPPRESS = 0

          FI;
    FI;
END;

NONCONFORMING-CODE-SEGMENT:
    IF L-Bit = 1 and D-BIT = 1 and IA32_EFER.LMA = 1
          THEN GP(new code segment selector); FI;
    IF (RPL > CPL) or (DPL  CPL)
          THEN #GP(new code segment selector); FI;
    IF CR4.FRED = 1 and CPL = 0 and L bit = 0
          THEN GP(new code segment selector); FI;
    IF segment not present
          THEN #NP(new code segment selector); FI;
    IF stack not large enough for return address
          THEN #SS(0); FI;
    tempEIP := DEST(Offset);
    IF target mode = Compatibility mode
          THEN tempEIP := tempEIP AND 00000000_FFFFFFFFH; FI;
    IF OperandSize = 16
          THEN tempEIP := tempEIP AND 0000FFFFH; FI; (* Clear upper 16 bits *)
    IF (IA32_EFER.LMA = 0 or target mode = Compatibility mode) and (tempEIP outside new code segment limit)
          THEN #GP(0); FI;
    IF tempEIP is non-canonical
          THEN #GP(0); FI;
    IF ShadowStackEnabled(CPL)
          IF IA32_EFER.LMA & CS.L
                tempPushLIP = RIP
          ELSE
                tempPushLIP = CSBASE + EIP;
          FI;
          tempPushCS = CS;


    FI;
    IF OperandSize = 32

          THEN
                Push(CS); (* Padded with 16 high-order bits *)
                Push(EIP);
                CS := DEST(CodeSegmentSelector);
                (* Segment descriptor information also loaded *)
                CS(RPL) := CPL;
                EIP := tempEIP;

          ELSE
                IF OperandSize = 16
                       THEN
                             Push(CS);
                             Push(IP);
                             CS := DEST(CodeSegmentSelector);
                             (* Segment descriptor information also loaded *)
                             CS(RPL) := CPL;
                             EIP := tempEIP;
                       ELSE (* OperandSize = 64 *)
                             Push(CS); (* Padded with 48 high-order bits *)
                             Push(RIP);
                             CS := DEST(CodeSegmentSelector);
                             (* Segment descriptor information also loaded *)
                             CS(RPL) := CPL;
                             RIP := tempEIP;
                FI;

    FI;
    IF ShadowStackEnabled(CPL)

          IF (IA32_EFER.LMA and DEST(CodeSegmentSelector).L) = 0
                (* If target is legacy or compatibility mode then the SSP must be in low 4GB *)
                IF (SSP & 0xFFFFFFFF00000000 != 0)
                       THEN #GP(0); FI;

          FI;
    (* align to 8 byte boundary if not already aligned *)
    tempSSP = SSP;
    Shadow_stack_store 4 bytes of 0 to (SSP  4)
    SSP = SSP & 0xFFFFFFFFFFFFFFF8H
    ShadowStackPush8B(tempPushCS); (* Padded with 48 high-order 0 bits *)
    ShadowStackPush8B(tempPushLIP); (* Padded 32 high-order bits of 0 for 32 bit LIP*)
    ShadowStackPush8B(tempSSP);
    FI;
    IF EndbranchEnabled(CPL)

          IF CPL = 3
                THEN
                       IA32_U_CET.TRACKER = WAIT_FOR_ENDBRANCH
                       IA32_U_CET.SUPPRESS = 0
                ELSE
                       IA32_S_CET.TRACKER = WAIT_FOR_ENDBRANCH
                       IA32_S_CET.SUPPRESS = 0

          FI;
    FI;
END;

CALL-GATE:


    IF call gate (DPL < CPL) or (RPL > DPL) or (CR4.FRED = 1)
          THEN #GP(call-gate selector); FI;

    IF call gate not present
          THEN #NP(call-gate selector); FI;

    IF call-gate code-segment selector is NULL
          THEN #GP(0); FI;

    IF call-gate code-segment selector index is outside descriptor table limits
          THEN #GP(call-gate code-segment selector); FI;

    Read call-gate code-segment descriptor;
    IF call-gate code-segment descriptor does not indicate a code segment
    or call-gate code-segment descriptor DPL > CPL

          THEN #GP(call-gate code-segment selector); FI;
    IF IA32_EFER.LMA = 1 AND (call-gate code-segment descriptor is
    not a 64-bit code segment or call-gate code-segment descriptor has both L-bit and D-bit set)

          THEN #GP(call-gate code-segment selector); FI;
    IF call-gate code segment not present

          THEN #NP(call-gate code-segment selector); FI;
    IF call-gate code segment is non-conforming and DPL < CPL

          THEN go to MORE-PRIVILEGE;
          ELSE go to SAME-PRIVILEGE;
    FI;
END;

MORE-PRIVILEGE:
    IF current TSS is 32-bit
          THEN
                TSSstackAddress := (new code-segment DPL  8) + 4;
                IF (TSSstackAddress + 5) > current TSS limit
                       THEN #TS(current TSS selector); FI;
                NewSS := 2 bytes loaded from (TSS base + TSSstackAddress + 4);
                NewESP := 4 bytes loaded from (TSS base + TSSstackAddress);
          ELSE
                IF current TSS is 16-bit
                       THEN
                             TSSstackAddress := (new code-segment DPL  4) + 2
                             IF (TSSstackAddress + 3) > current TSS limit
                                   THEN #TS(current TSS selector); FI;
                             NewSS := 2 bytes loaded from (TSS base + TSSstackAddress + 2);
                             NewESP := 2 bytes loaded from (TSS base + TSSstackAddress);
                       ELSE (* current TSS is 64-bit *)
                             TSSstackAddress := (new code-segment DPL  8) + 4;
                             IF (TSSstackAddress + 7) > current TSS limit
                                   THEN #TS(current TSS selector); FI;
                             NewSS := new code-segment DPL; (* NULL selector with RPL = new CPL *)
                             NewRSP := 8 bytes loaded from (current TSS base + TSSstackAddress);
                FI;
    FI;
    IF IA32_EFER.LMA = 0 and NewSS is NULL
          THEN #TS(NewSS); FI;
    Read new stack-segment descriptor;
    IF IA32_EFER.LMA = 0 and (NewSS RPL  new code-segment DPL
    or new stack-segment DPL  new code-segment DPL or new stack segment is not a
    writable data segment)
          THEN #TS(NewSS); FI


IF IA32_EFER.LMA = 0 and new stack segment not present
      THEN #SS(NewSS); FI;

IF CallGateSize = 32
      THEN
            IF new stack does not have room for parameters plus 16 bytes
                  THEN #SS(NewSS); FI;
            IF CallGate(InstructionPointer) not within new code-segment limit
                  THEN #GP(0); FI;
            SS := newSS; (* Segment descriptor information also loaded *)
            ESP := newESP;
            CS:EIP := CallGate(CS:InstructionPointer);
            (* Segment descriptor information also loaded *)
            Push(oldSS:oldESP); (* From calling procedure *)
            temp := parameter count from call gate, masked to 5 bits;
            Push(parameters from calling procedure's stack, temp)
            Push(oldCS:oldEIP); (* Return address to calling procedure *)
      ELSE
            IF CallGateSize = 16
                  THEN
                        IF new stack does not have room for parameters plus 8 bytes
                              THEN #SS(NewSS); FI;
                        IF (CallGate(InstructionPointer) AND FFFFH) not in new code-segment limit
                              THEN #GP(0); FI;
                        SS := newSS; (* Segment descriptor information also loaded *)
                        ESP := newESP;
                        CS:IP := CallGate(CS:InstructionPointer);
                        (* Segment descriptor information also loaded *)
                        Push(oldSS:oldESP); (* From calling procedure *)
                        temp := parameter count from call gate, masked to 5 bits;
                        Push(parameters from calling procedure's stack, temp)
                        Push(oldCS:oldEIP); (* Return address to calling procedure *)
                  ELSE (* CallGateSize = 64 *)
                        IF pushing 32 bytes on the stack would use a non-canonical address
                              THEN #SS(NewSS); FI;
                        IF (CallGate(InstructionPointer) is non-canonical)
                              THEN #GP(0); FI;
                        SS := NewSS; (* NewSS is NULL)
                        RSP := NewESP;
                        CS:IP := CallGate(CS:InstructionPointer);
                        (* Segment descriptor information also loaded *)
                        Push(oldSS:oldESP); (* From calling procedure *)
                        Push(oldCS:oldEIP); (* Return address to calling procedure *)
            FI;

FI;
IF ShadowStackEnabled(CPL) AND CPL = 3

      THEN
            IF IA32_EFER.LMA = 0
                  THEN IA32_PL3_SSP := SSP;
                  ELSE (* adjust so bits 63:N get the value of bit N1, where N is the CPU's maximum linear-address width *)
                        IA32_PL3_SSP := LA_adjust(SSP);
            FI;

FI;
CPL := CodeSegment(DPL)
CS(RPL) := CPL


IF ShadowStackEnabled(CPL)

      oldSSP := SSP

      SSP := IA32_PLi_SSP; (* where i is the CPL *)

      IF SSP & 0x07 != 0 (* if SSP not aligned to 8 bytes then #GP *)

           THEN #GP(0); FI;

      (* Token and CS:LIP:oldSSP pushed on shadow stack must be contained in a naturally aligned 32-byte region*)

      IF (SSP & ~0x1F) != ((SSP  24) & ~0x1F)

           #GP(0); FI;

      IF ((IA32_EFER.LMA and CS.L) = 0 AND SSP[63:32] != 0)

           THEN #GP(0); FI;

      expected_token_value = SSP        (* busy bit - bit position 0 - must be clear *)

      new_token_value = SSP | BUSY_BIT  (* Set the busy bit *)

      IF shadow_stack_lock_cmpxchg8b(SSP, new_token_value, expected_token_value) != expected_token_value

           THEN #GP(0); FI;

      IF oldSS.DPL != 3

           ShadowStackPush8B(oldCS); (* Padded with 48 high-order bits of 0 *)

           ShadowStackPush8B(oldCSBASE+oldRIP); (* Padded with 32 high-order bits of 0 for 32 bit LIP*)

           ShadowStackPush8B(oldSSP);

      FI;

FI;

IF EndbranchEnabled (CPL)

      IA32_S_CET.TRACKER = WAIT_FOR_ENDBRANCH

      IA32_S_CET.SUPPRESS = 0

FI;

END;

SAME-PRIVILEGE:
    IF CallGateSize = 32
          THEN
                IF stack does not have room for 8 bytes
                      THEN #SS(0); FI;
                IF CallGate(InstructionPointer) not within code segment limit
                      THEN #GP(0); FI;
                CS:EIP := CallGate(CS:EIP) (* Segment descriptor information also loaded *)
                Push(oldCS:oldEIP); (* Return address to calling procedure *)
          ELSE
               If CallGateSize = 16
                      THEN
                            IF stack does not have room for 4 bytes
                                  THEN #SS(0); FI;
                            IF CallGate(InstructionPointer) not within code segment limit
                                  THEN #GP(0); FI;
                            CS:IP := CallGate(CS:instruction pointer);
                            (* Segment descriptor information also loaded *)
                            Push(oldCS:oldIP); (* Return address to calling procedure *)
                      ELSE (* CallGateSize = 64)
                            IF pushing 16 bytes on the stack touches non-canonical addresses
                                  THEN #SS(0); FI;
                            IF RIP non-canonical
                                  THEN #GP(0); FI;
                            CS:IP := CallGate(CS:instruction pointer);
                            (* Segment descriptor information also loaded *)
                            Push(oldCS:oldIP); (* Return address to calling procedure *)
                FI;


    FI;
    CS(RPL) := CPL
    IF ShadowStackEnabled(CPL)

          (* Align to next 8 byte boundary *)
          tempSSP = SSP;
          Shadow_stack_store 4 bytes of 0 to (SSP  4)
          SSP = SSP & 0xFFFFFFFFFFFFFFF8H;
          (* push cs:lip:ssp on shadow stack *)
          ShadowStackPush8B(oldCS); (* Padded with 48 high-order bits of 0 *)
          ShadowStackPush8B(oldCSBASE + oldRIP); (* Padded with 32 high-order bits of 0 for 32 bit LIP*)
          ShadowStackPush8B(tempSSP);
    FI;
    IF EndbranchEnabled (CPL)
          IF CPL = 3

                THEN
                       IA32_U_CET.TRACKER = WAIT_FOR_ENDBRANCH;
                       IA32_U_CET.SUPPRESS = 0

                ELSE
                       IA32_S_CET.TRACKER = WAIT_FOR_ENDBRANCH;
                       IA32_S_CET.SUPPRESS = 0

          FI;
    FI;
END;

TASK-GATE:
    IF task gate DPL < CPL or RPL
          THEN #GP(task gate selector); FI;
    IF task gate not present
          THEN #NP(task gate selector); FI;
    Read the TSS segment selector in the task-gate descriptor;
    IF TSS segment selector local/global bit is set to local
    or index not within GDT limits
          THEN #GP(TSS selector); FI;
    Access TSS descriptor in GDT;
    IF descriptor is not a TSS segment
          THEN #GP(TSS selector); FI;
    IF TSS descriptor specifies that the TSS is busy
          THEN #GP(TSS selector); FI;
    IF TSS not present
          THEN #NP(TSS selector); FI;
    SWITCH-TASKS (with nesting) to TSS;
    IF EIP not within code segment limit
          THEN #GP(0); FI;

END;

TASK-STATE-SEGMENT:
    IF TSS DPL < CPL or RPL
    or TSS descriptor indicates TSS not available
          THEN #GP(TSS selector); FI;
    IF TSS is not present
          THEN #NP(TSS selector); FI;
    SWITCH-TASKS (with nesting) to TSS;
    IF EIP not within code segment limit
          THEN #GP(0); FI;


END;

Banderas afectadas

Todas las banderas se ven afectadas si se produce un interruptor de tarea; ninguna bandera se ve afectada si no se produce un interruptor de tarea.

Excepciones

Modo protegido
#GP(0)Si el objetivo se compensaoperando de destinoestá más allá del nuevo límite de segmento de código.el selector de segmentodentroel operando de destinoesNULL. Si el códigoselector de segmentoen la puertaNULL. Siun operando de memoriadirección efectiva está fuera del límite de segmento CS, DS, ES, FS o GS. Si el registro DS, ES, FS o GS se utiliza para acceder a la memoria y contiene unNULL selector de segmento. Si el modo objetivo es el modo de compatibilidad ySSPno está en bajo 4GB.SSPen IA32 PLi SSPCPL) no es 8 byte alineado. Si el token y el marco de la pila para ser empujado en la pila de sombras no están contenidos en una región de 32 bytes naturalmente alineada de la pila de sombras. Si el token de "supervisor Shadow Stack" en la nueva pila de sombras está marcado ocupado. Si el modo de destino es de 32 bits o modo de compatibilidad, peroSSPdirección en "supervisor sombra pila" token está más allá de 4 GB. SiSSPdirección en "supervisor sombra pila" token no coincideSSPdirección en IA32 PLi SSP (donde soy el nuevoCPL).
#GP(selector)Si un segmento de código o puerta oTSSíndice selector está fuera de los límites de la tabla descriptor.el selector de segmentodentroel operando de destinono es para un segmento de código de conformación, segmento de código no conforme, puerta de llamada, puerta de tarea o segmento de estado de tarea.DPLpara un segmento de código no conforme no es igual alCPLo elRPLpara el segmentoselector de segmentoes mayor que elCPLSiDPLpara un segmento de código de conformación es mayor que elCPLSiDPLde una puerta de llamada, de tarea oTSSDescriptor de segmento es menor que elCPLo que elRPLde la puerta de llamada, de tareas oTSS's selector de segmento. Si el descriptor del segmentoun selector de segmentode una puerta de llamada no indica que es un segmento de código.el selector de segmentode una puerta de llamada está más allá de los límites de la mesa descriptor.DPLpara un segmento de código obtenido de una puerta de llamada es mayor que elCPL. Siel selector de segmentopara unTSStiene su bit local/global fijado para local. Si unTSSdescriptor de segmento especifica queTSSestá ocupado o no está disponible.
#SS(0)Si empujar la dirección de retorno, los parámetros o el puntero del segmento de la pila excede los límites del segmento de la pila, cuando no se produce ningún interruptor de la pila. Si la dirección efectiva un operando de memoria está fuera del límite del segmento SS.
#SS(selector)Si empujar la dirección de retorno, parámetros o puntero de segmento de pila en la pila excede los límites del segmento de la pila, cuando se produce un interruptor de pila. Si el registro SS se está cargando como parte de un interruptor de pila y el segmento apuntado no está presente. Si el segmento de la pila no tiene espacio para la dirección de retorno, parámetros o puntero de segmento de la pila, cuando se produce el interruptor de la pila.
#NP(selector)Si un segmento de código, segmento de datos, puerta de llamada, puerta de tarea, o TSS no está presente.
#TS(selector)Si la nueva pila selector de segmento y ESP están más allá del final del TSS. Si la nueva pila selector de segmento es NULL.
#PF(fault-code)Si el RPL de la nueva pila selector de segmento en el TSS no es igual al DPL del código
#AC(0)Se accede a un segmento.
#UDSiDPLdel descriptor del segmento de la pila para el nuevo segmento de la pila no es igual alDPLdel descriptor del segmento de código. Si el nuevo segmento de la pila no es un segmento de datos writable. Si el índice de selección del segmento de la pila es fuera de los límites de la tabla de descriptor.un fallo de paginaSi la comprobación de alineación está habilitada y se hace una referencia de memoria no alineada mientras que el nivel de privilegio actual es 3.LOCKprefijo se utiliza.
Modo real
#GPSi la dirección efectiva un operando de memoria está fuera del límite de segmento CS, DS, ES, FS o GS. Si el offset objetivo está más allá del límite de segmento de código.
#UDSi se utiliza el prefijo LOCK.
Modo virtual-8086
#GP(0)Si un operando de memoria dirección efectiva está fuera del límite de segmento CS, DS, ES, FS o GS. Si el offset objetivo está más allá del límite de segmento de código. #PF(fault-code) Si un fallo de pagina ocurre.
#AC(0)Si la comprobación de alineación está habilitada y se hace una referencia de memoria no alineada.
#UDSi se utiliza el prefijo LOCK.
Modo de compatibilidad
Las mismas excepciones que en modo protegido.
#GP(selector)Si una dirección de memoria accedida por el selector está en espacio no canónico. Si las transiciones FRED están habilitadas y el selector hace referencia a una puerta de llamada.
#GP(0)Si el objetivo offset en el operando de destino no es canónico.
Modo de 64 bits
#GP(0)Si una dirección de memoria no es canónica.operando de destinono es canónico.el selector de segmentodentroel operando de destinoesNULL. Si el códigoselector de segmentoen la puerta de 64 bitsNULL. Si el modo objetivo es el modo de compatibilidad ySSPno está en bajo 4GB.SSPen IA32 PLi SSPCPL) no es 8 byte alineado. Si el token y el marco de la pila para ser empujado en la pila de sombras no están contenidos en una región de 32 bytes naturalmente alineada de la pila de sombras. Si el token de "supervisor Shadow Stack" en la nueva pila de sombras está marcado ocupado. Si el modo de destino es de 32 bits o modo de compatibilidad, peroSSPdirección en "sombra supervisor" pila token está más allá de 4 GB. SiSSPdirección en "supervisor sombra pila" token no coincideSSPdirección en IA32 PLi SSP (donde soy el nuevoCPL).
#GP(selector)Si el segmento de código o la puerta de llamada de 64 bits está fuera de los límites de la tabla de descriptores. Si el segmento de código o la puerta de llamada de 64 bits superpone el espacio no canónico.
#SS(0)Si el descriptor del segmento apuntado por el selector de segmento en el operando de destino no es
#SS(selector)para un segmento de código de conformación, segmento de código no conforme, o puerta de llamada de 64 bits.
#NP(selector)Si el descriptor del segmento apuntado por el selector de segmento en el operando de destino es un
#TS(selector)segmento de código y tiene tanto el D-bit y el conjunto Lbit.
#UDSi el DPL para un segmento de código no conforme no es igual al CPL, o el RPL para el
#PF(fault-code)selector de segmento del segmento es mayor que el CPL.
#AC(0)SiDPLpara un segmento de código de conformación es mayor que elCPLSiDPLde una puerta de llamada de 64 bits es menos que laCPLo que elRPLsi el campo de tipo superior de una puerta de llamada de 64 bits no es 0x0.el selector de segmentode una puerta de llamada de 64 bits está más allá de los límites de la tabla descriptor.DPLpara un segmento de código obtenido de una puerta de llamada de 64 bits es mayor que elCPL. Si el descriptor del segmento de código apuntado por el selector en la puerta de 64 bits no tiene el conjunto L-bit y el D-bit claro. Si el descriptor del segmento paraun selector de segmentodesde la puerta de llamada de 64 bits no indica que es un segmento de código.FREDlas transiciones están habilitadas y el selector hace referencia a una puerta de llamada.FREDlas transiciones están habilitadas,CPLes 0, y la instrucción entraría en modo de compatibilidad. Si empujar el offset de retorno o el selector de CS en la pila excede los límites del segmento de la pila cuando no se produce el interruptor de la pila.un operando de memoriadirección efectiva está fuera del límite del segmento SS. Si la dirección de la pila está en una forma no canónica. Si empuja los valores antiguos del selector de SS,puntero de pila, EFLAGS, selector de CS, offset, o código de error en la pila viola el límite canónico cuando se produce un interruptor de pila. Si un segmento de código o puerta de llamada de 64 bits no está presente.RSPexcede el límite delTSS. (Modo de 64 bits solamente) Si una llamada de lejos es directa a una dirección absoluta en memoria.LOCKprefijo es usado.un fallo de paginaSi la comprobación de alineación está habilitada y se hace una referencia de memoria no alineada mientras que el nivel de privilegio actual es 3.

Fuentes