Minima Anonyma Tabularia Ex Reti

nihil vacuum neque sine signo apud MATER

Liber Octavus

 

Questa è la zine ufficiale di Familia, un gruppo che ha come oggetto di studio la programmazione virale.

MATER ha come scopo l’esame delle tecniche di programmazione virale e delle problematiche ad esse associate. Questa è una raccolta di contributi volontari (e non) di alcuni code-writers del pianeta, in lingua italiana ed è rivolta soprattutto a chi si avvicina per la prima volta al mondo dei virus e necessita dei concetti di base che spesso sono dati per scontati nelle zines reperibili in Rete. Non è, tuttavia, una esemplificazione discorsiva priva di contenuto tecnico: per comprendere gli esempi ivi contenuti è necessaria una minima conoscenza dell’architettura di un elaboratore e del linguaggio assembler.

E’ nostra convinzione che una migliore conoscenza delle metodologie infettive digitali sia la principale strada per accrescere la sicurezza degli utenti e fornire un contributo a chi opera nel settore della programmazione. Ritenendo il vero nemico della sicurezza la disinformazione, auspichiamo che una più profonda comprensione in questo campo dissipi i dubbi, aiuti la ricerca e contribuisca al progresso dell’educazione informatica. Sursum Corda ! 

 

 

ATTENZIONE

Questa pubblicazione contiene informazioni e codice sorgente relativi alla sicurezza informatica. Lo scopo di queste informazioni è di aiutare gli utenti ad accrescere la propria capacità di programmazione. Questo materiale è a puro scopo didattico e non include codice distruttivo né documenti attinenti ad alcuna attività illegale. Si declina ogni responsabilità nel caso chiunque utilizzi le suddette informazioni per creare, compilare e diffondere intenzionalmente programmi diretti a danneggiare o interrompere un sistema informatico o telematico, ovvero a provocarne l'interruzione, totale o parziale, o l'alterazione del suo funzionamento Art. 615-quinquies (Legge n. 547/93 pubblicata in Gazzetta Ufficiale n. 305 del 30.12.1993)

 

 

 

 § MATER Liber Octavus §

 

   POLIMORFISMO - 2

 

   indice

               1.istruzioni e codici

               2.formato delle istruzioni INTEL

               3.codifica delle istruzioni

               4.esempi

 

 

1.istruzioni e codici   

 

Prima di dare vedere come è fatto un MP dobbiamo dare uno sguardo al formato delle istruzioni della famiglia di processori x86. Un MP è un generatore di codice, ed è quindi necessario sapere come funzionano i codici operativi (opcode) del processore. Per chi si addentrerà nello studio deve disporre di una tabella di tutte gli opcode del processore che può essere trovata sui manuali Intel.

 

Ogni istruzione che effettua un’operazione, è composta da una parte fissa più una parte che cambia in base al registro (o ai registri) usati con quella specifica operazione.

 

Facciamo un esempio:

 

           mov     reg16,imm16

 

E' un’operazione che muove il valore imm16 (un immediato da 16 bit) nel registro a 16 bit scelto. Vediamo la codifica di un paio di esempi di questa operazione:

 

       mov     ax,0h           B8 0000

       mov     cx,0h           B9 0000

       mov     bx,0h           BB 0000

 

Come si può notare ad un opcode di partenza (B8 in questo caso), viene aggiunto un dato valore in base al registro scelto. In particolare è possibile creare codice opportuno per qualsiasi registro aggiungendo il valore rispettivo secondo la tabella:

 

       Registro         Valore

     AX     -  000b

     CX     -  001b

     DX     -  010b

     BX     -  011b

     SP     -  100b

     BP     -  101b

     SI     -  110b

     DI     -  111b

 

Conoscendo quindi l'opcode di partenza (trovato nelle specifiche del processore) possiamo facilmente generare codice per qualsiasi  registro disponibili.

Con registri a 8 bit le cose rimangono invariate. Cambia ovviamente l'opcode di partenza (per esempio mov reg8,imm8 corrisponde nell’istruzione base mov al,0h al codice B0 00). La tabella di addizione per i registri  si trasforma in:

 

       Registro        Valore

     AL     -  000b

     CL     -  001b

     DL     -  010b

     BL     -  011b

     AH     -  100b

     CH     -  101b

     DH     -  110b

     BH     -  111b

 

Con registri dword (a 32bit) deve essere aggiunto prima il byte di prefisso 66h o 67h (ma questo dipende dal comando voluto).

Quando l’istruzione richiede due registri, ad esempio per un generico mov reg16_1,reg16_2 basta prendere l'opcode base dell'istruzione (in questo caso 8B C0, dalla documentazione vedrete che il primo byte rimane fisso quindi per i registri andremo a cambiare solo il secondo), sommare il valore del registro sorgente (reg16_2), quindi sommare il valore del registro di destinazione moltiplicato per 8 (che poi si riduce ad un shift a sinistra di 3). Quindi ad esempio per un:

mov cx,dx      avremo:

C0h + 02h + (8 * 01h) e quindi il codice per l'istruzione voluta sarà 8B CA.

 

Dove l'istruzione richiede un valore immediato (come nell'esempio precedente), un indirizzo di memoria, un offset da un registro o qualcos'altro, oltre al codice verrà aggiunta di seguito dopo l'opcode di base (ad esempio prima nel mov ax,0000 dopo il B8 chiaramente ce' una word 0h).

 

 

2. Formato delle istruzioni nell’architettura Intel

 

La codifica delle istruzioni Intel è un sottoinsieme del formato generale mostrato nella figura in basso. Le istruzioni consistono di un prefisso (opzionale e in qualsiasi ordine), un opcode primario da 1 o 2 bytes, una forma di indirizzamento costituita da un  ModR/M da 1 byte (se richiesto) e talvolta da un byte SIB (Scale-Index-Base), da uno spiazzamento (se richiesto), e da un dato immediato (se richiesto).

Ricordiamo che R/M è come è costruita l’istruzione ( con base, con indici, con due registri) e Mod identifica cosa effettua l’indicizzazione ( DI, BP... ).

 

 

Intel Architecture Instruction Format (dal manuale Intel, vol II)

 

    Prefissi                           Opcode             ModR/M               SIB                   Displacement             Immediate

---------------------------------------------------------------------------------------------------------------------------------------------------

Fino a 4 prefissi           opcode di 1              1 byte                1 byte                spiazzamento           dati immediati

di un byte                       o 2 bytes           (se richiesto)     (se richiesto)         0,1,2 o 4 bytes          0,1,2 o 4 bytes

(opzionale)                                                  

---------------------------------------------------------------------------------------------------------------------------------------------------

 

 ModRam:             7      6 5           3 2         0

                             +-------+-----------+---------+

                             | Mod  |   Reg/     |  R/M   |

                             |          | Opcode  |           |

                             + ------------------------------+

 

SIB:                      7      6 5           3 2         0

                             +-------+-----------+---------+

                             | Scale|  Index     | Base  |

                             |          |                |           |

                             + ------------------------------+

 

Prefissi

I prefissi delle istruzioni sono divisi in 4 gruppi:

Lock and repeat prefixes.

— F0H—LOCK prefix.

— F2H—REPNE/REPNZ prefix (used only with string instructions).

— F3H—REP prefix (used only with string instructions).

— F3H—REPE/REPZ prefix (used only with string instructions).

Segment override.

— 2EH—CS segment override prefix.

— 36H—SS segment override prefix.

— 3EH—DS segment override prefix.

— 26H—ES segment override prefix.

— 64H—FS segment override prefix.

— 65H—GS segment override prefix.

Operand-size override, 66H

Address-size override, 67H

 

Opcode primario

l’opcode primario può essere da 1 o 2 bytes. Talvolta si incontra un campo codificato a 3 bit nel byte ModR/M. Questi campi definiscono la direzione dell’operazione, la misura dello spiazzamento, la codifica dei registri, i codici di condizione, il segno.

Ecco ad esempio la codifica di tutti i tipi di istruzione MOV (dal manuale Intel, vol. II):

 

88 / r          MOV r/m8,r8                     Move r8 to r/m8

89 / r          MOV r/m16,r16                 Move r16 to r/m16

89 / r          MOV r/m32,r32                 Move r32 to r/m32

8A / r          MOV r8,r/m8                     Move r/m8 to r8

8B / r          MOV r16,r/m16                 Move r/m16 to r16

8B / r          MOV r32,r/m32                 Move r/m32 to r32

8C / r          MOV r/m16,Sreg**            Move segment register to r/m16

8E / r          MOV Sreg,r/m16**            Move r/m16 to segment register

A0              MOV AL, moffs8*              Move byte at ( seg:offset) to AL

A1              MOV AX, moffs16*            Move word at ( seg:offset) to AX

A1              MOV EAX, moffs32*          Move doubleword at ( seg:offset) to EAX

A2              MOV moffs8*,AL                Move AL to ( seg:offset)

A3              MOV moffs16*,AX             Move AX to ( seg:offset)

A3              MOV moffs32*,EAX           Move EAX to ( seg:offset)

B0+ rb        MOV r8,imm8                     Move imm8 to r8

B8+ rw       MOV r16,imm16                 Move imm16 to r16

B8+ rd        MOV r32,imm32                 Move imm32 to r32

C6 / 0         MOV r/m8,imm8                 Move imm8 to r/m8

C7 / 0         MOV r/m16,imm16             Move imm16 to r/m16

C7 / 0         MOV r/m32,imm32              Move imm32 to r/m32

 

 

Ad esempio:

89/r   MOV  r/m32, r32  à Move r32 to r/m32

sarà quindi uguale a:

       MOV  EAX  , EDX

 

 

Simbologia utilizzata dall’Intel:

 

rel8—indirizzo relativo in un range da 128 bytes prima della fine dell’istruzione a 127 bytes dopo al fine dell’istruzione.

rel16 e rel32—indirizzo relativo allo stesso code segment come  l’istruzione è assemblata.

ptr16:16 e ptr16:32—puntatore FAR, che punta in un segmento diverso da quello dell’istruzione.

 

r8—uno dei registri di uso generale da un bytes: AL, CL, DL, BL, AH, CH, DH, o BH.

r16—uno dei registri di uso generale da una word: AX, CX, DX, BX, SP, BP, SI, o DI.

r32—uno dei registri di uso generale da una doubleword: EAX, ECX, EDX, EBX, ESP, EBP,ESI, o EDI.

imm8—un valore immediato da un byte.

imm16—un valore immediato da 16 bits. E’ un numero tra –32,768 e +32,767 inclusi.

imm32— un valore immediato da 32 bits. E’ un numero tra +2,147,483,647 e –2,147,483, 648 inclusi.

r/m8—un operando da 1 byte che può contenere un registro generale da un byte (AL, BL, CL, DL, AH, BH, CH, and DH), o un byte dalla memoria.

r/m16— un operando da 2 bytes che può contenere un registro generale da 2 bytes: AX, BX, CX,

DX, SP, BP, SI, e DI o due bytes di memoria.

r/m32—un registro doubleword general-purpose: EAX, EBX, ECX, EDX, ESP, EBP, ESI, e EDI.

m—un operando da 16- o 32-bit in memoria.

m8— un operando da 1 byte in memoria, usualmente espresso come una variabile o nome di array ma puntato dai registri DS:(E)SI o ES:(E)DI.

m16—come sopra, con operando da una word. Questa nomenclatura è usata solo con le istruzioni con stringhe.

m32—come sopra, con operando di doubleword. Questa nomenclatura è usata solo con le istruzioni con stringhe.

m64—come sopra con operando di quadword. Solo usata con l’istruzione CMPXCHG8B.

 

 

m16:16, m16:32—un operando di memoria contenente un puntatore far composto da due numeri. Il numero alla sinistra della colonna corrisponde al selettore del puntatore al segmento. Il numero alla destra corrisponde al suo offset.

m16&32, m16&16, m32&32— Un operando di memoria che consiste in copie la cui misura è indicata alla sinistra e alla destra di &

moffs8, moffs16, moffs32—una variabile di memoria (memory offset) di tip byte, word, o doubleword usata con alcune varianti dell’istruzione MOV.

Sreg—un registro di segmento: ES=0, CS=1, SS=2, DS=3, FS=4, and GS=5.

m32real, m64real, m80real—un operando floating point single-, double-, e extended-real (rispettivamente)

m16int, m32int, m64int—rispettivamente un operando floating-point word-, short-, e long-integer

ST or ST(0)—l’elemento più in alto (top element) dello stack registri FPU.

ST(i)—l’ i-elemento dalla cima dello stack FPU  (i da 0 a 7)

mm—un registro MMX™ . I registri a  64-bit MMX sono da MM0 a MM7.

mm/m32— i “low order 32 bits” di un registro MMX register o un operando di 32-bit- I registri MMX vanno   da MM0 a MM7.

 mm/m64—Un registro MMX o un operando di 64-bit.

 

 

3. Codifica delle istruzioni - approfondimento

 

 

Vedremo come viene costruita un’istruzione in un MP. Riprendiamo lo scheletro di una istruzione, semplificato:

 

     8 bits            2          3          3             8 o 16 bits         8 o 16 bits  

  Istruzione     Mod     Reg     R/M        Spiazzamento           Dati    

      1 byte         -------1 byte------          1 o 2 bytes        1 o 2 bytes  

 

per semplicità si utilizzerà la seguente notazione:
 
       campo reg  - codice che contiene il registro usato
       campo sreg - codice che contiene il registro di segmento
       campo r/m  - come è costruita l0istruzione( con base, indicizzata, etc.)     
       campo mod  - cosa effettua l’indicizzazione (es. DI, BP, etc.)
       campo dir  - direzione
       campo w    - marcatore word 
 
si danno le seguenti tabelle:
 
       campo reg:
       ~~~~~~~~~~
       AX or AL - 000  =  0
       CX or CL - 001  =  1
       DX or DL - 010  =  2
       BX or BL - 011  =  3
       SP or AH - 100  =  4
       BP or CH - 101  =  5
       SI or DH - 110  =  6
       DI or BH - 111  =  7
 
Quando è codificata un’istruzione dove vengono utilizzati registri da un byte o da una word, la maniera per sapere se si tratta di uno o dell’altro tipo di registri è quella di controllare il bit 'w'. Se è 1 allora vengono utilizzati registri word, se è 0 allora vengono utilizzati registri byte.
 
       campo sreg
       ~~~~~~~~~~
       ES - 001  =  1
       CS - 011  =  3
       SS - 101  =  5
       DS - 111  =  7
 
       campo r/m 
       ~~~~~~~~~
       00 - base o indice
       01 - base o indice con spiazzamento a 8 bit 
       10 – base o indice con spiazzamento a 16 bit 
       11 – due registri
 
       campo mod (se r/m è base o indice)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       000 - [BX+SI]
       001 - [BX+DI]
       010 - [BP+SI]
       011 - [BP+DI]
       100 - [SI]
       101 - [DI]
       110 - se R/M = 00 un offset diretto o [BP]
       111 - [BX]
 
       overrides di segmento
       ~~~~~~~~~~~~~~~~~
       ES - 00100110 - 26h
       CS - 00101110 - 2Eh
       SS - 00110110 - 36h
       DS - 00111110 - 3Eh
 
    Direzione
       Se settato, reg è la destinazione e mod è l’origine, altrimenti viceversa.
 
Vediamo come viene generata un’istruzione mov. Se disassembliamo un programma che contiene la linea:
MOV BX, [SI+0134h]  vedremo il seguente opcode: 8B 9C 34 01
o, in binario:
 
        10001011100111000011010000000001
 
che significa:
 
        100010 | 1 | 1 | 10  | 011 | 100 | 0011010000000001 |
        mov      d   w   r/m   reg   mod         dati
 
in cui
                  d (direzione) = 1, da 'mod' a 'reg'
                  w             = 1 (il bit word)
                  r/m           = 10 (base con spiazzamento a 16-bit)
                  reg (registro)= 011 (BX)
                  mod           = 100 ([SI])
                  dati          = 0134h (lo spiazzamento a 16 bit aggiunto a SI)
 
 
Per creare un’istruzione Mov reg, [si+imm] “vuota” dovremmo avere:
 
        100010  1  1 10 000 100 0000000000000000, 
 
cioè
 
        10001011 10000100 0000000000000000
                     ^     dati dati dati
                  registro
 
La sequenza:  10001001100011011000000000000000 
                   MOV [DI+1000h], CX 
in quanto:
           d   = 1
           r/m = 10
           mod = 101
           reg = 001
 
 
Altri esempi, ricavati con il debugger:

      

    MOV ax, 1234h    ; mov reg16,imm16     

    B8h+RegWord imm16

    B83412 -- 10111000 00110100 00010010

 

    XOR ax,1234h    35h imm16

    353412 -- 00110101 00110100 00010010

 

    AND bx,1234h     ; and regmem16,imm16

    81h \4 imm16             

    81E33412 -- 10000001 11100011 00110100 00010010

 

    ADD dx, 1234h    ; regmem16,imm16  

    81h \0 imm16

    81C23412 -- 10000001 11000010 00110100 00010010

 

     mov ax,1234h

     B83412

 

casi di indirizzamenti (per la codifica in binario provate da soli, come esercizio):

 

     mov al,[bx]           ; indirizzamento indiretto

     8A07

 

     mov al,cs:[bx]        ; ind.indiretto con override prefix        

     AL,[BX] – 8A07

 

     mov al, 20h[bx]       ; indirizzamento indicizzato (spiazzam=20h)

     AL,[BX+20] – 8A4720

 

     mov al, ss:20h[bx]    ; idem con override

     come sopra

 

     mov al,[bx][si]       ; ind.indiciz. con base

     AL,[BX+SI] – 8A00

 

     mov al, 20h[bx][si]   ; idem con override

     AL,[BX+SI+20] – 8A4020

 

     mov al, [bp+si+20h]   ; idem con override

     come sopra

 

 

4.codifica di alcune istruzioni - esempi

 
MOV 
       1) mov reg, imm    1011, w, reg, imm
                           - se w = 0 imm è 8  bit -> 2 byte
                           - se w = 1 imm è 16 bit -> 3 byte
       2) mov reg, reg
          mov reg, mem
          mov mem, reg
                          100010, d, w, r/m, reg, mod, dati
                           - se r/m = 00                -> 2 byte
                           - se r/m = 01 dati is 8  bit -> 3 byte 
                           - se r/m = 10 dati is 16 bit -> 4 byte 
       3) mov sreg, reg
          mov reg, sreg
                          100011, d, 0, 1, sreg, reg, 1
                           - 2 byte 
 
XCHG 
    xchg reg, reg
    xchg reg, mem
    xchg mem, reg
                          100001, w, r/m, reg, mod, dati
 
Operazioni sullo Stack
 
    PUSH reg    - 01010, reg
    POP reg     - 01011, reg
    PUSH sreg   - 000, sreg, 10
    POP sreg    - 000, sreg, 11
    PUSH imm    - 01101000, dati
    PUSH mem    - 11111111, r/m, 110, mod, dati
    POP mem     - 1000111, r/m, 0000, mod, dati
    PUSHA       - 01100000
    POPA        - 01100001
    PUSHF       - 10011100
    POPF        - 10011101
 
istruzioni logiche
 
    1) XOR
       1.1) XOR reg, reg  001100, d, w, 11, reg1, reg2
            d = 1 solo se reg1 = reg2
 
       1.2) XOR reg, imm  100000, w, r, 11110, reg, dati
            r = 0 registro è 8 bit altrimenti è 16 bit
 
       1.3) XOR reg, mem
            XOR mem, reg
                          00110, d, w, r/m, reg, mod, dati
 
    2) OR
       2.1) OR reg, reg   0000100, d, w, 11, reg1, reg2
       2.2) OR reg, imm   100000, w, r, 11001, reg
       2.3) OR reg, mem
            OR mem, reg
                          000010, d, w, r/m, reg, mod, dati
 
    3) AND
       3.1) AND reg, reg   001000, d, w, 11, reg1, reg2
       3.2) AND reg, imm   100000, w, r, 11000, reg
       3.3) AND reg, mem
            AND mem, reg
                           001000, d, w, r/m, reg, mod, dati
 
    4) NOT
       4.1) NOT reg        1111011111010, reg
       4.2) NOT mem        1111011, w, r/m, 010, mod
 
    5) NEG
       5.1) NEG reg        1111011111011, reg
       5.2) NEG mem        1111011, w, r/m, 011, mod
 
    6) TEST
       6.1) TEST reg, reg  1000010, w, 11, reg1, reg2
       6.2) TEST reg, imm  1111011, w, 11010, reg, dati
 
 
    7) CMP
      7.1) CMP reg, reg    0011101, d, w, 11, reg1, reg2
       7.2) CMP reg, imm   100000, w, r, 11111, reg
       7.3) CMP reg, mem
            CMP mem, reg
                           001110, d, w, r/m, reg, mod, dati
 
 
istruzioni aritmetiche
 
    1) ADD
       1.1) ADD reg, reg   0000001, w, 11, reg, reg
       1.2) ADD reg, imm   100000, w, r, 11000, reg
       1.3) ADD reg, mem
            ADD mem, reg
                           000000, d, w, r/m, reg, mod
 
    2) ADC
       2.1) ADC reg, reg   0001001, w, 11, reg, reg
       2.2) ADC reg, imm   100000, w, r, 11010, reg
       2.3) ADC reg, mem
            ADC mem, reg
                           000100, d, w, r/m, reg, mod
 
    3) SUB
       3.1) SUB reg, reg   0010101, w, 11, reg, reg
       3.2) SUB reg, imm   100000, w, r, 11101, reg
       3.3) SUB reg, mem
            SUB mem, reg   001010, d, w, r/m, reg, mod
 
    4) SBB
       4.1) SBB reg, reg   0001101, w, 11, reg, reg
       4.2) SBB reg, imm   100000, w, r, 11011, reg
       4.3) SUB reg, mem
            SUB mem, reg
                           000110, d, w, r/m, reg, mod
 
    5) INC  01000, reg16        1111111111000, reg8
 
    6) DEC  01001, reg16        1111111011001, reg8
 
istruzioni di shifting
 
    1) SHR
       1.1) SHR reg, 1    1101000, w, 11101, reg
       1.2) SHR reg, imm  1100000, w, 11101, reg
       1.3) SHR reg, cl   1101001, w, 11101, reg
 
    2) SHL
       2.1) SHL reg, 1    1101000, w, 11100, reg
       2.2) SHL reg, imm  1100000, w, 11100, reg
       2.3) SHL reg, cl   1101001, w, 11100, reg
 
    3) ROR
       3.1) ROR reg, 1    1101000, w, 11001, reg
       3.2) ROR reg, imm  1100000, w, 11001, reg
       3.3) ROR reg, cl   1101001, w, 11001, reg
 
    4) ROL
       4.1) ROL reg, 1    1101000, w, 11000, reg
       4.2) ROL reg, imm  1100000, w, 11000, reg
       4.3) ROL reg, cl   1101001, w, 11000, reg
 
    5) RCL
       5.1) RCL reg, 1    1101000, w, 11010, reg
       5.2) RCL reg, imm  1100000, w, 11010, reg
       5.3) RCL reg, cl   1101001, w, 11010, reg
 
    6) RCR
       6.1) RCR reg, 1    1101000, w, 11011, reg
       6.2) RCR reg, imm  1100000, w, 11011, reg
       6.3) RCR reg, cl   1101001, w, 11011, reg
 
 
istruzioni di flag
 
    CLI   - 11111010
    STI   - 11111011
    CLD   - 11111100
    STD   - 11111101
    CLC   - 11111000
    STC   - 11111001
    CMC   - 11110101
    SAHF  - 10011110
    LAHF  - 10011111
 
istruzioni di salto
 
      1) JMP SHORT - EBh, dati8
      2) JMP NEAR  - E9h, dati16
      3) JMP FAR   - EAh, dati
 
dati è un segment:offset dati in formato inverso.
Esempio: jmp far 1000:432fh = EAh, 2f43h, 0010h
 
I salti condizionali (nota che dati8 è un numero signed a 8 bit, va da  -127  a  -1  il jump è verso l’alto altrimenti verso il basso.  Il jump è calcolato dalla fine della’istruzione di JMP.
Ciò significa che un’struzione  JE 00 è un  jump all’sitruzione successiva (più sotto), mentre un’istruzione JE 02 è un jump che salta ai du ebytes dopo l’opcode del jump.
 
      4)  JBE/JNA      - 76h, dati8
      5)  JLE/JNG      - 7Eh, dati8
      6)  JB/JNAE/JC   - 72h, dati8
      7)  JL/JNGE      - 7Ch, dati8
      8)  JZ/JE        - 74h, dati8
      9)  JNE/JNZ      - 75h, dati8
      10) JAE/JNB/JNC  - 73h, dati8
      11) JGE/JNL      - 7Dh, dati8
      12) JA/JNBE      - 77h, dati8
      13) JG/JNLE      - 7Fh, dati8
      14) JCXZ         - E3h, dati8
      15) JNO          - 71h, dati8
      16) JO           - 70h, dati8
      17) JP/JPE       - 7Ah, dati8
      18) JNP/JPO      - 7Bh, dati8
      19) JNS          - 79h, dati8
      20) JS           - 78h, dati8
 
      21) LOOP - E2h, dati8
 
      22) CALL SHORT - E8h, dati8
 
      23) RETN - C3h
      24) RETF - CBh
      35) IRET - CFh
 
      36) INT - CD, dati8
 
altre istruzioni
 
     1) lea reg, mem
 
        10011, d, w, r/m, reg, mod, dati
 
        per es LEA DI, [BP+1000h] dovrebbe essere:
 
            10011,  0, 1,  10, 111, 110, 0010
            Opcode  d  w  r/m  reg  mod  dati
 
 
Un esempio di creazione dello scheletro di istruzioni
 
abbiamo i seguenti:
 
         kreg = CX = 00000001
         creg = BX = 00000011
 
e vogliamo creare:
 
           (1)      XOR CX, BX
           (2)      MOV [DI], CX
 
per la (1) abbiamo lo scheletro:
 
         001100, d, w, 11, reg1, reg2
 
che codifichiamo come:
 
         00110000 11000000
 
e quindi completiamo:
 
         00110000 or   11000000 or
         00000011      00001011
         --------      --------
         00110011      11001011 e abbiamo 0011001111001011 = 33CBh
 
 
Per la (2) lo scheletro è:
 
         100010, d, w, r/m, reg, mod, dati
 
che codifichiamo come:
 
         10001000 00000000
 
e quindi completiamo:
 
         10001000 or  00000000 or
         00000001     00001101
         --------     --------
         10001001     00001101 = 1000100100001101 = 890Dh
 
Così abbiamo:
 
             33 CB xor cx, bx
             89 0D mov [di], cx