## ALP Programming Guide and Reference

[prev][next][parent][TOC]

### Operation

Note: The following operational description applies not only to the above instructions but also to external interrupts and exceptions.

    IF PE = 0
    THEN CALL REAL-ADDRESS-MODE;
    ELSE
      CALL PROTECTED-MODE;
      IF task gate
      THEN CALL TASK-GATE;
      ELSE
      CALL TRAP-OR-INT-GATE; (* PE=1, int/trap gate *)
      IF code segment is non-conforming AND DPL < CPL
      THEN
        IF VM=0
        THEN CALL INT-TO-INNER-PRIV; (*PE=1,int/trap gate,DPL<CPL,VM=0*)
        ELSE CALL INT-FROM-V86-MODE; (* PE=1, int/trap gate, DPL<CPL,
                      VM=1 *)
        FI;
        ELSE (* PE=1, int/trap gate, DPL ò CPL *)
          IF code segment is conforming OR code segment DPL = CPL
        THEN CALL INT-TO-SAME-PRIV;
        ELSE #GP(CS selector + EXT); (* PE=1, int/trap gate, DPL>CPL *)
          FI;
          FI;
        FI;
    FI;
    END;

    REAL-ADDRESS-MODE PROC
      Push (FLAGS);
      IF  0; (* Clear interrupt flag *)
      TF  0; (* Clear trap flag *)
      Push(CS);
      Push(IP);
      (* No error codes are pushed *)
      CS  IDT[Interrupt number * 4].selector;
      IP  IDT[Interrupt number * 4].offset;
    (* Start processing in real address mode *)
    REAL-ADDRESS-MODE ENDPROC

    PROTECTED-MODE PROC
      Interrupt vector must be within IDT table limits,
         else #GP(vector number * 8+2+EXT);
      Descriptor AR byte must indicate interrupt gate, trap gate, or task gate,
         else #GP(vector number * 8+2+EXT);
      IF software interrupt (* i.e. caused by INT n, INT 3, or INTO *)
      THEN
        IF gate descriptor DPL<CPL
        THEN #GP(vector number * 8+2+EXT); (* PE=1, DPL<CPL, software interrupt *)
        FI;
      FI;
      Gate must be present, else #NP(vector number * 8+2+EXT);
    PROTECTED-MODE ENDPROC

    TRAP-OR-INT-GATE PROC
      Examine CS selector and descriptor given in the gate descriptor;
      Selector must be non-null, else #GP (EXT);
      Selector must be within its descriptor table limits
        ELSE #GP(selector+EXT);
      Descriptor AR byte must indicate code segment
        ELSE #GP(selector + EXT);
      Segment must be present, else #NP(selector+EXT);
    TRAP-OR-INT-GATE ENDPROC

    INT-TO-INNER-PRIV PROC
      (* PE=1, DPL<CPL and non-conforming, (* PE=1, int/trap gate, DPL<CPL, VM=0 *)
      Check selector and descriptor for new stack in current TSS;
        Selector must be non-null, else #TS(EXT);
        Selector index must be within its descriptor table limits
          ELSE #TS(SS selector+EXT);
        Selector's RPL must equal DPL of code segment, else #TS(SS
          selector+EXT);
        Stack segment DPL must equal DPL of code segment, else #TS(SS
          selector+EXT);
        Descriptor must indicate writable data segment, else #TS(SS
          selector+EXT);
        Segment must be present, else #SS (SS selector+EXT);
      If 32-bit gate
      THEN New stack must have room for 20 bytes else #SS(0)
      ELSE New stack must have room for 10 bytes else #SS(0)
      FI;
      Instruction pointer must be within CS segment boundaries else #GP(0);
      Load new SS and eSP value from TSS;
      If 32-bit gate
        THEN CS:EIP  selector:offset from gate;
      ELSE CS:IP  selector:offset from gate;
      FI;
      Load CS descriptor into invisible portion of CS register;
      Load SS descriptor into invisible portion of SS register;
      IF 32-bit gate
    THEN
        Push (long pointer to old stack) (* 3 words padded to 4 *);
        Push (EFLAGS);
        Push (long pointer to return location) (* 3 words padded to 4 *);
    ELSE
        Push (long pointer to old stack) (* 2 words *);
        Push (FLAGS);
        Push (long pointer to return location) (* 2 words *);
      FI;
      Set CPL to new code segment DPL;
      Set RPL of CS to CPL;
      IF interrupt gate THEN IF  0 (* interrupt flag to 0 (disable) *); FI;
      TF  0;
      NT  0;
    INT-FROM-INNER-PRIV ENDPROC

    INT-FROM-V86-MODE PROC
      Check selector and descriptor for new stack in current TSS;
      Selector must be non-null, else #TS(EXT);
      Selector index must be within its descriptor table limits
        ELSE #TS(SS selector+EXT);
      Selector's RPL must equal DPL of code segment, else #TS(SS
        selector+EXT);
      Stack segment DPL must equal DPL of code segment, else #TS(SS
        selector+EXT);
      Descriptor must indicate writable data segment, else #TS(SS
        selector+EXT);
      Segment must be present, else #SS(SS selector+EXT);
      IF 32-bit gate
        THEN New stack must have room for 20 bytes else #SS(0)
        ELSE New stack must have room for 10 bytes else #SS(0)
      FI;
      Instruction pointer must be within CS segment boundaries else #GP(0);
      IF IOPL < 3
      THEN
        #GP(0); (*V86 monitor trap: PE=1,int/trap gate, DPL<CPL, VM=1, IOPL<3*)
      ELSE (* IOPL=3 *)
        IF GATE'S_DPL = 3
        THEN
          IF TARGET'S_CPL <> 0
          THEN #GP(0);
          ELSE
            TempEFlags  EFLAGS;
            VM  0;
            TF  0;
            IF service through Interrupt Gate
                THEN IF  0;
            FI;
            TempSS  SS;
            TempESP  ESP;
            SS  TSS.SS0; (* Change to level 0 stack segment *)
        ESP  TSS.ESP0; (* Change to level 0 stack pointer *)
        Push(GS); (* padded to two words *)
            Push(FS); (* padded to two words *)
        Push(DS); (* padded to two words *)
        Push(ES); (* padded to two words *)
        GS  0; (* segment registers nullified - invalid in
           protected mode *)
            FS  0;
        DS  0;
        ES  0;
        Push(TempSS); (* Padded to two words *)
        Push(TempESP);
        Push(TempEFlags);
        Push(CS); (* Padded to two words *)
        Push(EIP);
            CS:EIP  selector:offset from interrupt gate;
            (* Starts processing of new routine in Protected Mode *)
          FI;
       ELSE (* GATE'S_DPL <> 3 *)
          #GP(0);
        FI;
      FI;
    INT-FROM-V86-MODE ENDPROC

    INT-TO-SAME-PRIV PROC
        (* PE=1, DPL=CPL or conforming segment *)
      IF 32-bit gate
      THEN Current stack limits must allow pushing 10 bytes, else #SS(0);
      ELSE Current stack limits must allow pushing 6 bytes, else #SS(0);
      FI;

    IF interrupt was caused by exception with error code
    THEN Stack limits must allow push to two more bytes;
    ELSE #SS(0);
    FI;
    Instruction pointer must be in CS limit, else #GP(0);
    IF 32-bit gate
    THEN
      Push (EFLAGS);
      Push (long pointer to return location); (* 3 words padded to 4 *)
      CS:EIP  selector:offset from gate;
    ELSE (* 16-bit gate *)
      Push (FLAGS);
      Push (long pointer to return location); (* 2 words *)
      CS:IP  selector:offset from gate;
    FI;
    Load CS descriptor into invisible portion of CS register;
      Set the RPL field of CS to CPL;
      Push (error code); (* if any *)
      IF interrupt gate THEN IF  0; FI;
      TF  0;
      NT  0;
    INT-TO-SAME-PRIV ENDPROC

    TASK-GATE PROC (* PE=1, task gate *)
      Examine selector to TSS, given in task gate descriptor;
        Must specify global in the local/global bit, else #TS(TSS selector);
        Index must be within GDT limits, else #TS(TSS selector);
        AR byte must specify available TSS (bottom bits 00001);
          else #TS(TSS selector);
        TSS must be present, else #NP(TSS selector);
      SWITCH-TASKS with nesting to TSS;
      IF interrupt was caused by fault with error code
      THEN
        Stack limits must allow push of two more bytes, else #SS(0);
        Push error code onto stack;
      FI;
      Instruction pointer must be in CS limit, else #GP(0);
    TASK-GATE ENDPROC