8086 (and 8088) Instruction Set (includ 80186 (and 80188) extensions, w/o 8087) author Neil Franklin, last modification 2008.07.24 Basics: ------- All numbers and bit patterns in this file are usually given in hex, seldom in binary, never in decimal or octal. Sources for this data: ---------------------- 1. Introduction to 80x86 sections of "The Art of Assembly", old MS-DOS Edition, from http://webster.cs.ucr.edu/AoA/DOS/pdf/0_AoAPDF.html . 2. Shortlist of 8086/88/186/186/286(realmode) instructions published in German computer magazine c't issue Oct 1989 page 341. 3. Detailed 80x86 Information, Sandpile Website, from http://www.sandpile.org/ Contradicts 2. 4. Intel Pentium Spftware Developers Manuals volumes 1+2 from http://developer.intel.com/design/pentium/manuals/24319001.pdf and http://developer.intel.com/design/pentium/manuals/24319101.pdf . Very unlikely to contain errors. Of course errors of my own are to be expected. Registers: ---------- (in order: data, address, pc, flags, auxillary) AX CX DX BX 16bit General Purpose Registers, naming as: AX = Accumulator, CX = Counter, DX = Data, BX = Base AL CL DL BL 8bit bottom halves of AX CX DX BX AH CH DH BH 8bit top halves of AX CX DX BX, naming as: *L = Low 8bit, *H = High 8bit, *X = eXtended 8+8bit BP SI DI 16bit Address Registers, naming as: BP = BasePointer, SI = SourceIndex, DI = DestinationIndex despite this usually SI+DI pointers, BP base for indexing SP 16bit Stack Pointer (push pre-decr, pop post-incr) PC 16bit Program Counter F 16bit Flags Register CS DS ES SS 16bit Segment Registers, naming as: CS = Code Segment, DS = Data S, SS = Stack S, ES = Extra S Flags Register: --------------- (in order: from MSB/15 to LSB/0, in 2 groups 15 to 8 and 7 to 0) 1 unused 1 unused 1 unused 1 unused O Overflow (arithmetic result carry bit6->bit7) D Direction (0|1 makes string instr increment|decrement SI and DI) I Interrupt (1 enables interrupts) T Trace (1 traps to INT 1 after every instruction) S Sign (result bit7 set) Z Zero (result all bits cleared) 0 unused A Auxillary Carry (arithmet result carry bit3->bit4, used only by AA*/DA*) 0 unused P Parity (result parity even) 1 unused C Carry (arithmetic result carry bit7->"bit8") General policy seems to be: - arithmetic add/subtract (incl AA*/DA*): set all OSZAPC - multiplication: set all OSZAPC (with SZAP allways random) - division: set all OSZAPC (with all allways random) - decrement/increment: set OSZAP, leave C unchanged - logic stuff: set all OSZAPC (with OC allways set constant, A allways random) - shift: set all OSZAPC (with O only shift 1 else random, A allways random) - rotate: set only OC (with O only shift 1 else random) - load/store/move/in/out/stack: leave all flags - jump/call/return: leave all flags Memory: ------- Program+Data memory 512*2*8bit (20bit byte address space) I/O devices 128*2*8bit or 32k*2*8bit (8bit or 16bit byte address space) Addressing Modes, in Assembler Syntax: -------------------------------------- (in order: reg, immediate, address, reg indirect, reg indexed, pc) AX CX DX BX BP SI DI SP 16bit register AL CL DL BL AH CH DH BH 8bit register n immediate8 nn immediate16 l level8 (only ENTER instr) [dd] "displacement-only16" (actually direct-address16) [BX] [BP] [SI] [DI] register indirect [BX+d] [BP+d] [SI+d] [DI+d] reg base + displacement/offset8 (or [BB][d] syntax) [BX+dd] [BP+dd] [SI+dd] [DI+dd] reg base + displacement/offset16 (or [BB][dd] syntax) [dd+BX] [dd+BP] [dd+SI] [dd+DI] "displace16" (base16) + reg index (or [dd][II] or dd[II]) (is technically same as register base + offset16) [BX+SI] [BX+DI] [BP+SI] [BP+DI] [SI+BX] [SI+BP] [DI+BX] [DI+BP] reg base + reg index (or [BB][II] syntax) [BX+SI+d] etc reg base + reg index + offset8 (or [BB][II][d] syntax) [BX+SI+dd] etc reg base + reg index + offset16 (or [BB][II][dd] syntax) [BX+d+SI] etc reg base + offset8 + reg index (or [BB][d][II] syntax) (is technically same as reg base + offset8 + reg index) [BX+dd+SI] etc reg base + offset16 + reg index (or [BB][dd][II] syntax) (is technically same as reg base + offset16 + reg index) [dd+BX+SI] etc base16 + reg offset + reg index (or [dd][OO][II] or dd...) (is technically same as reg base + offset16 + reg index) -nameless- string pointer auto-inc/dec-rement (only string instr) p short-port-address8 (only IN/OUT instr) [DX] register-port-address16 (only IN/OUT instr) -nameless- stack pointer indirect decrement/increment (only PUSH/POP) dddd offset16 (only CALL/JMP instr) ss:dd segment16 and offset16 (only CALLF/JMPF instr) d displacement8 (only JMP/Jcc/JCX*/LOOP* instr) Instruction Formats, in Machine Code Bytes: ------------------------------------------- (in order: simple, immediate, register, mod-reg-r/m, in/out, esc, jump, prefix) oo opcode8 oonn opcode8 immediate8 oonnnn opcode8 immediate-low8 immediate-high8 (= little endian) oonnnnll opcode8 immediate-low8 immediate-high8 level8 or opcode5+reg-address3 os opcode6+segmreg-address2 oorm opcode8 mod2+reg3+reg/mem3 oormdd opcode8 mod2+reg3+reg/mem3 displacement8 oormdddd opcode8 mod2+reg3+reg/mem3 displ-low8 displ-high8 (= little endian) oosm opcode8 mod2+segmreg-address3+reg/mem3 ooomd* opcode8 mod2+opc3+reg/mem3 ev-displ(-low)8 ev-displ-high8 (= l e) ooomd*nn opcode8 mod2+opc3+reg/mem3 ev-displ(-low)8 ev-displ-high8 immed8 ooomd*nnnn opcode8 mod2+opc3+reg/mem3 ev-d(-l)8 ev-d-h8 imm-l8 imm-h8 (= l e) oopp opcode8 port-address8 oodd opcode8 displacement8 oodddd opcode8 displacement-low8 displacement-high8 (= little endian) ooddddssss opcode8 disp-low8 disp-high8 segment-low8 segment-high8 (= l e) ocdd opcode4+condition4 displacement8 ss** prefix-segmentswitch6+segmreg-address2 above... F0** prefix-buslock8 above... rroo prefix-repeatstring8 string-opcode8 Instruction Bit Patterns and Operations: ---------------------------------------- (in order: functional grouping: arithmetic, data transfer, jump, auxillary) arithmetic/logic 00ooo0dw mmrrrmmm ..ooo... ........ opcode operation ..000... ........ ADD dest = dest + source; FlagsOSZAPC "ADD" ..001... ........ OR dest = dest bitwise-OR source; FlagsOSZAPC "OR" ..010... ........ ADC dest = dest + source + FlagC; FlagsOSZAPC "ADd with Carry" ..011... ........ SBB dest = dest - source - FlagC; FlagsOSZAPC "SuBtract with Borrow" ..100... ........ AND dest = dest bitwise-AND source; FlagsOSZAPC "AND" ..101... ........ SUB dest = dest - source; FlagsOSZAPC "SUBtract" ..110... ........ XOR dest = dest bitwise-excl-OR source; FlagsOSZAPC "eXclusive OR" ..111... ........ CMP FlagsOSZAPC = dest - source "CoMPare" ......d. ........ direction ......0. mm...mmm dest = register/memory ..rrr... source = register ......1. mm...mmm source = register/memory ..rrr... dest = register .......w ........ width .......0 ........ 8bit .......1 ........ 16bit 100000sw mmooommm ......s. ........ sign extend immediate value ......0. ........ 8bit: get 8bit, 16bit: get 16bit ......1. ........ 8bit: get 8bit, 16bit: get 8bit and sign extend to 16bit .......w ........ width .......0 ........ 8bit .......1 ........ 16bit ........ mm...mmm dest = register/memory ........ ..ooo... opcode operation (flags and names as above) ........ ..000... ADD n|nn dest = dest + immediate8|16 ........ ..001... OR n|nn dest = dest bitwise-OR immediate8|16 ........ ..010... ADC n|nn dest = dest + immediate8|16 + FlagC ........ ..011... SBB n|nn dest = dest - immediate8|16 - FlagC ........ ..100... AND n|nn dest = dest bitwise-AND immediate8|16 ........ ..101... SUB n|nn dest = dest - immediate8|16 ........ ..110... XOR n|nn dest = dest bitwise-excl-OR immediate8|16 ........ ..111... CMP n|nn Flags = dest - immediate8|16 00ooo10w ..ooo... opcode operation (flags and names as above) ..000... ADD AL|AX,n|nn AL|AX = AL|AX + immediate8|16 ..001... OR AL|AX,n|nn AL|AX = AL|AX bitwise-OR immediate8|16 ..010... ADC AL|AX,n|nn AL|AX = AL|AX + immediate8|16 + FlagC ..011... SBB AL|AX,n|nn AL|AX = AL|AX - immediate8|16 - FlagC ..100... AND AL|AX,n|nn AL|AX = AL|AX bitwise-AND immediate8|16 ..101... SUB AL|AX,n|nn AL|AX = AL|AX - immediate8|16 ..110... XOR AL|AX,n|nn AL|AX = AL|AX bitwise-excl-OR immediate8|16 ..111... CMP AL|AX,n|nn FlagsOSZAPC = AL|AX - immediate8|16 .......w width .......0 8bit .......1 16bit increment/decrement 0100oddd ....o... opcode operation ....0... INC dest = dest + 1; FlagsOSZAP "INCrement" ....1... DEC dest = dest - 1; FlagsOSZAP "DECrement" .....ddd destination .....000 AX .....000 CX .....000 DX .....000 BX .....000 SP .....000 BP .....000 SI .....000 DI 1111111w mmooommm .......w ........ width .......0 ........ 8bit .......1 ........ 16bit ........ mm...mmm dest = register/memory ........ ..ooo... opcode operation (flags and names as above) ........ ..000... INC dest = dest + 1 ........ ..001... DEC dest = dest - 1 shift/rotate 11a000aw mmooommm ..a...a. ........ amount ..0...0. ........ n|nn constant immediate8 (only from 80186/80188) ..1...0. ........ 1 constant 1 ..1...1. ........ CL variable register CL .......w ........ width .......0 ........ 8bit .......1 ........ 16bit ........ mm...mmm dest = register/memory ........ ..ooo... opcode operation ........ ..000... ROL dest = dest(bit6..0,7); FlagC=dest(bit7); FlagsOC "ROtate Left" ........ ..001... ROR dest = dest(bit0,7..1); FlagC=dest(bit0); FlagsOC "ROtate Right" ........ ..010... RCL FlagC,dest = dest,FlagC; FlagsOC "Rotate through Carry Left" ........ ..011... RCR dest,FlagC = FlagC,dest; FlagsOC "Rotate through Carry Right" ........ ..100... SHL FlagC,dest = dest,0; FlagsOSZAPC "Shift Logical Left" = SAL additional name for SHL "Shift Arithmetc Left" ........ ..101... SHR dest,FlagC = 0,dest; FlagsOSZAPC "Shift Logical Right" ........ ..111... SAR dest,FlagC = dest(bit7),dest; FlagsOSZAPC "Shift Arithmetc Right" indexed address calculation oooooooo mmrrrmmm opcode operation 10001101 ........ LEA dest = source-address "Load Effective Address" ........ mm...mmm source = memory only ..rrr... dest = register test and 1-op arithmetic and multiplication/division 1111011w mmooommm .......w ........ width .......0 ........ 8bit .......1 ........ 16bit ........ mm...mmm dest/source = register/memory ........ ..ooo... opcode operation ........ ..000... TEST n|nn FlagsSZP = source bitwise-AND immed8|16 "TEST" ........ ..010... NOT dest = bitwise-NOT dest (flags none!) "NOT" ........ ..011... NEG dest = 0 - dest; FlagsOSZAPC "NEGation" ........ ..100... MUL AX|DX:AX = AL|AX * source; FlagsOSZAPC "unsigned MULtiply" ........ ..101... IMUL AX|DX:AX = AL|AX * source; FlagsOSZAPC "signed (Integer) MULtiply" ........ ..110... DIV if source = 0 then (div by zero trap) mem[--SP] = F; FlagsITA = 0 mem[--SP] = CS; mem[--SP] = PC; PC = mem[0*4] (address16); CS = mem[0*4+2] (segment16); AL|AX = AX|DX:AX / source; AH|DX = AX|DX:AX MOD source; FlagsOSZAPC "unsigned Divide" ........ ..111... IDIV if source = 0 then (div by zero trap) mem[--SP] = F; FlagsITA = 0 mem[--SP] = CS; mem[--SP] = PC; PC = mem[0*4] (address16); CS = mem[0*4+2] (segment16); AL|AX = AX|DX:AX / source; AH|DX = AX|DX:AX MOD source; FlagsOSZAPC "signed (Integer) Divide" ooooooow mmrrrmmm opcode operation 1000010. ........ TEST FlagsSZP = dest bitwise-AND source "TEST" .......w ........ width .......0 ........ 8bit .......1 ........ 16bit ........ mm...mmm dest = register/memory ..rrr... source = register ooooooow opcode operation 1010100. TEST AL|AX,n|nn FlagsSZP = AL|AX bitwise-AND immediate8|16 "TEST" .......w width .......0 8bit .......1 16bit ooooooso mmrrrmmm opcode operation (only from 80186/80188) 011010.1 ........ IMUL dest = source * immed8|16; FlagsOSZAPC "signed (Integer) MULtiply" ......s. ........ sign extend immediate value ......0. ........ get 16bit ......1. ........ get 8bit and sign extend to 16bit ........ mm...mmm source = register/memory ..rrr... dest = register floating point 11011ooo mmooommm opcode operation .....ooo ..ooo... ESC trigger FPU operation oooooo "ESCape to 8087 fpu" ........ mm...mmm dest/source = register/memory oooooooo opcode operation 10011011 WAIT wait for outstanding FPU exeptions "WAIT for 8087 fpu" other specialised arithmetic oooooooo opcode operation 00001111 DAA if AL(bit3..0) > 9 or FlagA = 1 then AL = AL + 6; FlagAC if AL(bit7..4) > 9 or FlagC = 1 then AL = AL + 96 FlagsOSZAPC "Decimal Adjust al after Addition" 00011111 DAS if AL(bit3..0) > 9 or FlagA = 1 then AL = AL - 6; FlagAC if AL(bit7..4) > 9 or FlagC = 1 then AL = AL - 96 FlagsOSZAPC "Decimal Adjust al after Subtraction" 00101111 AAA if AL(bit3..0) > 9 or FlagA = 1 then AL = AL + 6; AH =+ 1 AL = AL bitwise-AND 15; FlagsOSZAPC "Ascii Adjust al after Addition" 00111111 AAS if AL(bit3..0) > 9 or FlagA = 1 then AL = AL - 6; AH =- 1 AL = AL bitwise-AND 15; FlagsOSZAPC "Ascii Adjust al after Subtraction" 10011000 CBW AX = sign-extend AL (flags none!) "Convert Byte to Word" 10011001 CWD DX:AX = sign-extend AX (flags none!) "Convert Word to Doubleword" 11010100 AAM AH = AL / immed8; AL = AL MOD immed8 (immed8 default 10) FlagsOSZAPC "Ascii Adjust ax after Multiplication" 11010101 AAD AL = AH * immed8 + AL; AH = 0 (immed8 default 10) FlagsOSZAPC "Ascii Adjust ax before Division" load/store/register oooooodw mmrrrmmm opcode operation 100010.. ........ MOV dest = source "MOVe" ......d. ........ direction ......0. mm...mmm dest = register/memory ..rrr... source = register ......1. mm...mmm source = register/memory ..rrr... dest = register .......w ........ width .......0 ........ 8bit .......1 ........ 16bit ooooooow mm000mmm opcode operation 1000101. ........ MOV register/memory = immediate8|16 "MOVe" .......w ........ width .......0 ........ 8bit .......1 ........ 16bit oooowrrr opcode operation 1011.... MOV reg,immediate8|16 "MOVe" ....w... width ....0... 8bit ....1... 16bit .....rrr register (same as rrr in mmrrrmmm) oooooodw opcode operation 101000.. MOV dest = source "MOVe" ......d. direction ......0. dest = AL|AX, source = mem[dddd] ......1. source = mem[dddd], dest = AL|AX .......w width .......0 8bit .......1 16bit oooooooo opcode operation 11010111 XLAT AL = mem[BX+AL] "table look up trans(X)LATion" stack push/pop/frame 1ooo1111 mmooommm .ooo.... ..ooo... opcode operation .000.... ..000... POP dest = mem[SP++] "POP word from stack" .111.... ..110... PUSH mem[--SP] = source "PUSH word onto stack" ........ mm...mmm dest/source = register/memory ooooooso opcode operation (only from 80186/80188) 011010.0 PUSH mem[--SP] = immediate8|16 "PUSH immediate onto stack" ......s. sign extend immediate value ......0. get 16bit ......1. get 8bit and sign extend to 16bit 0101orrr ....o... opcode operation ....0... PUSH mem[--SP] = reg "PUSH register onto stack" ....1... POP reg = mem[SP++] "POP register from stack" .....rrr register 16bit (same as rrr in mmrrrmmm) oooooooo opcode operation (only from 80186/80188) 01100000 PUSHA mem[--..--SP] = AX,CX,DX,BX,origSP,BP,SI,DI "PUSH All" 01100001 POPA DI,SI,BP,dropword,BX,DX,CX,AX = mem[SP++..++] "POP All" oooooooo opcode operation (only from 80186/80188) 11001000 ENTER meme[--SP] = BP; copy display (2nd immed8 words); BP = SP; SP = SP - 1st immed16 "ENTER procedure, create stack frame" 11001001 LEAVE SP = BP; BP = meme[SP++] "LEAVE provedure, remove stack frame" exchange ooooooow mmrrrmmm opcode operation 1000011. ........ XCHG dest <=> source "eXCHanGe" .......w ........ width .......0 ........ 8bit .......1 ........ 16bit ........ mm...mmm dest = register/memory ..rrr... source = register ooooorrr opcode operation 10010... XCHG AX, AX <=> register "eXCHanGe AX with register" .....rrr register 16bit (same as rrr in mmrrrmmm) input and output 1110m1dw ....m... mode (IO source/destination address) ....0... io[immediate8] ....1... io[DX] ......d. opcode operation/direction ......0. IN AL|AX = source "INput from port" ......1. OUT destination = AL|AX "OUTput to port" .......w width .......0 8bit .......1 16bit string handling oo10ooow oo..ooo. opcode operation 01..110. INS mem[ES:DI+-] = io[DX] (only from 80186/80188) "INput String from port" 01..111. OUTS io[DX] = mem[DS:SI+-] (only from 80186/80188) "OUTput String to port" 10..010. MOVS mem[ES:DI+-] = mem[DS:SI+-]; "MOVe String" 10..011. CMPS FlagsOSZAPC = mem[DS:SI+-] - mem[ES:DI+-]; "CoMPare String" 10..101. LODS AL|AX = mem[DS:SI+-] "LOaD String" 10..110. STOS mem[ES:DI+-] = AL|AX "STOre String" 10..111. SCAS FlagsOSZAPC = AL|AX - mem[DS:SI+-] "SCAn String" (DI and/or SI: +- direction depends on D Flag: 0 = +, 1 = -) .......w width .......0 8bit .......1 16bit (DI and/or SI: +- size depends on width: 1 if 8bit, 2 if 16bit) segment registers oooooodo mm0ssmmm opcode operation 100010.0 ........ MOV dest = source "MOVe" ......d. ........ direction ......0. mm...mmm dest = register/memory ...ss... source = segment register ......1. mm...mmm source = register/memory ...ss... dest = segment register 1100010o mmrrrmmm .......o ........ opcode operation .......0 ........ LES dest = mem[source]; ES = mem[source+2] "Load far pointer into register and Extra Segment register" .......1 ........ LDS dest = mem[source]; DS = mem[source+2] "Load far pointer into register and Data Segment register" ........ mm...mmm source = memory only ..rrr... dest = register 000ss11o ...ss... segment register (same as ss in mm0ssmmm) .......o opcode operation .......0 PUSH mem[--SP] = segment reg "PUSH segment register onto stack" .......1 POP segment reg = mem[SP++] "POP segment register from stack" (POP CS only on 8086/8088, from 80186/80186 on disabled) ooossooo opcode operation 001..110 select segment for data memory accesses of next instruction ...ss... segment register (same as ss in mm0ssmmm) ...00... ES: "Extra Segment select(:)" ...01... CS: "Code Segment select(:)" ...10... SS: "Stack Segment select(:)" ...11... DS: "Data Segment select(:)" other specialised data transfer oooooooo opcode operation 11110000 LOCK lock bus against multiprocessors while next instr "LOCK" (valid before ADD, ADC, AND, DEC, INC NEG, NOT, OR, SUB, SBB and XCHG) jumps/subroutines and reset/interrupts oooooooo opcode operation 10010000 NOP do nothing (alias for XCHG AX,AX) "No OPeration" 10011010 CALLF ss:dd mem[--SP] = CS; mem[--SP] = PC; PC = mem[PC++] (address16); CS = mem[PC++] (segment16) "CALL Far" 11000010 RET nn PC = mem[SP++]; SP = SP + immediate16 "RETurn" 11000011 RET PC = mem[SP++] "RETurn" 11001010 RETF nn PC = mem[SP++]; CS = mem[SP++]; SP = SP + immed16 "RET F" 11001011 RETF PC = mem[SP++]; CS = mem[SP++] "RETurn Far" 11001100 INT 3 mem[--SP] = F; FlagsITA = 0 mem[--SP] = CS; mem[--SP] = PC; PC = mem[3*4] (address16); CS = mem[3*4+2] (segment16); "INTerrupt 3" 11001101 INT n mem[--SP] = F; FlagsITA = 0 mem[--SP] = CS; mem[--SP] = PC; PC = mem[immed8*4] (address16); CS = mem[immed8*4+2] (segment16); "INTerrupt" 11001111 IRET PC = mem[SP++]; CS = mem[SP++]; F = mem[SP++] "Interrupt RETurn" 11101000 CALL dd mem[--SP] = PC; PC = mem[PC++] (address16) "CALL" 11101001 JMP dd PC = mem[PC++] (address16) "JuMP" 11101010 JMPF ss:dd PC = mem[PC++] (address16); CS = mem[PC++] (segment16) "JuMP Far" 11101011 JMP d PC = PC + mem[PC+] (displacement8) "JuMP" 11110100 HLT NOP until RESET/INT "HaLT" ---- pin RESET FlagsITA = 0; PC = 0000; CS = FFFF "RESET" ---- pin NMI mem[--SP] = F; FlagsITA = 0 mem[--SP] = CS; mem[--SP] = PC; PC = mem[2*4] (address16); CS = mem[2*4+2] (segment16); "Non Maskable Interrupt" ---- pin INT mem[--SP] = F; FlagsITA = 0 mem[--SP] = CS; mem[--SP] = PC; PC = mem[vector8*4] (address16); CS = mem[vector8*4+2] (segment16); "Interrupt" --- flag T mem[--SP] = F; FlagsITA = 0 mem[--SP] = CS; mem[--SP] = PC; PC = mem[1*4] (address16); CS = mem[1*4+2] (segment16); "Trace flag" 11111111 mmooommm ........ mm...mmm source = register/memory ........ ..ooo... opcode operation ........ ..010... CALLI mem[--SP] = PC; PC = source (address16) "CALL Indirect" ........ ..011... CALLIF mem[--SP] = PC; PC = source (address16); CS = source (segment16) "CALL Indirect Far" ........ ..100... JUMPI PC = source (address16) "JuMP Indirect" ........ ..101... JUMPIF PC = source (address16); CS = source (segment16) "JuMP Indirect Far" branches/conditionals oooooooo mmrrrmmm opcode operation (only from 80186/80188) 01100010 ........ BOUND if source < mem[dest] OR source > mem[dest+2] mem[--SP] = F; FlagsITA = 0 mem[--SP] = CS; mem[--SP] = PC; PC = mem[5*4] (address16); CS = mem[5*4+2] (segment16) "check array index against BOUNDs" ........ mm...mmm dest = memory only ..rrr... source = register oooocccc oooo.... opcode operation 0111.... Jcc d if condition then PC = PC + mem[PC+] (displacement8) "Jump if cc" ....cccc cc condition ....0000 O O = 1 "Overflow" ....0001 NO O = 0 "Not Overflow" ....0010 C C = 1 "Carry" = B additional name for C "Below" = NAE additional name for C "Not Above or Equal" ....0011 NC C = 0 "Not Carry" = NB additional name for NC "Not Below" = AE additional name for NC "Above or Equal" ....0100 Z Z = 1 "Zero" = E additional name for Z "Equal" ....0101 NZ Z = 0 "Not Zero" = NE additional name for NZ "Not Equal" ....0110 BE C = 1 OR Z = 1 "Below or Equal" = NA additional name for BE "Not Above" ....0111 NBE C = 0 AND Z = 0 "Not Below or Equal" = A additional name for NBE "Above" ....1000 S S = 1 "Sign" ....1001 NS S = 0 "Not Sign" ....1010 P P = 1 "Parity" = PE additional name for P "Parity Even" ....1011 NP P = 0 "Not Parity" = PO additional name for NP "Parity Odd" ....1100 L S XOR O = 1 "Less" = NGE additional name for L "Not Greater or Equal" ....1101 NL S XOR O = 0 "Not Less" = GE additional name for NL "Greater or Equal" ....1110 LE S XOR O = 1 OR Z = 1 "Less or Equal" = NG additional name for LE "Not Greater" ....1111 NLE S XOR O = 0 AND Z = 0 "Not Less or Equal" = G additional name for NLE "Greater" oooooooo opcode operation 11001110 INTO if FlagO = 1 then mem[--SP] = F; FlagsITA = 0 mem[--SP] = CS; mem[--SP] = PC; PC = mem[4*4] (address16); CS = mem[4*4+2] (segment16); "INTerrupt Overflow" 11100000 LOOPNZ CX = CX - 1; if CX != 0 AND FlagZ = 0 then PC = PC + mem[PC+] (displacement8) "decrement cx and LOOP while not zero and Not Zero flag" = LOOPNE additional name for LOOPNZ "decrement cx and LOOP while not zero and Not Equal" 11100001 LOOPZ CX = CX - 1; if CX != 0 AND FlagZ = 1 then PC = PC + mem[PC+] (displacement8) "decrement cx and LOOP while not zero and Zero flag" = LOOPE additional name for LOOPZ "decrement cx and LOOP while not zero and Equal" 11100010 LOOP CX = CX - 1; if CX != 0 then PC = PC + mem[PC+] (displacement8) "decrement cx and LOOP while not zero" 11100011 JCXZ if CX = 0 then PC = PC + mem[PC+] (displacement8) "Jump if CX is Zero" 11110010 REPNZ while CX != 0 AND FlagZ = 0 repeat string instr "REPeat string while Not Zero flag" = REPNE additional name for REPNZ "REPeat string while Not Equal" (only REPNZ/REPNE for CMPS|SCAS) 11110011 REP while CX != 0 repeat string instr "REPeat string" = REPZ while CX != 0 AND FlagZ = 1 repeat string instr "REPeat string while Zero flag" = REPE additional name for REPZ "REPeat string while Equal" (REP for INS|OUTS|MOVS|LODS|STOS, REPZ/REPE for CMPS|SCAS) flags 11111ffo .....ff. f flag .....00. C Carry .....01. I Interrupt .....10. D Direction .......o opcode operation .......0 CLf Flagf = 0 "CLear f flag" .......1 STf Flagf = 1 "SeT f flag" (STI delayed by 1 instr, so can be used before RET or IRET) oooooooo opcode operation 10011100 PUSHF mem[--SP] = F "PUSH flags register onto stack" 10011101 POPF F = mem[SP++] "POP flags register from stack" 10011110 SAHF lowbyte(F) = AH "Store AH into status Flags" 10011111 LAHF AH = lowbyte(F) "Load into AH status Flags" 11010110 SALC if FlagC = 0 then AL = 0 else AL = 255 (effect AL = 0 - FlagC) (flags none!) "Set AL fron flag C" 11110101 CMC FlagC = NOT FlagC "CoMplement Carry flag" Mode-Register-Register/Memory Postbyte Bit Patterns and Operations: ------------------------------------------------------------------- standard form: mmrrrmmm mm...mmm 1st parameter: mode + register or memory 00...000 mem[BX+SI] 00...001 mem[BX+DI] 00...010 mem[BP+SI] 00...011 mem[BP+DI] 00...100 mem[SI] 00...101 mem[DI] 00...110 mem[dddd] 00...111 mem[BX] 01...000 mem[BX+SI+dd] 01...001 mem[BX+DI+dd] 01...010 mem[BP+SI+dd] 01...011 mem[BP+DI+dd] 01...100 mem[SI+dd] 01...101 mem[DI+dd] 01...110 mem[BP+dd] 01...111 mem[BX+dd] 10...000 mem[BX+SI+dddd] 10...001 mem[BX+DI+dddd] 10...010 mem[BP+SI+dddd] 10...011 mem[BP+DI+dddd] 10...100 mem[SI+dddd] 10...101 mem[DI+dddd] 10...110 mem[BP+dddd] 10...111 mem[BX+dddd] 11...000 AL|AX 11...001 CL|CX 11...010 DL|DX 11...011 BL|BX 11...100 AH|SP 11...101 CH|BP 11...110 DH|SI 11...111 BH|DI ..rrr... 2nd parameter: register only ..000... AL|AX ..001... CL|CX ..010... DL|DX ..011... BL|BX ..100... AH|SP ..101... CH|BP ..110... DH|SI ..111... BH|DI segment register form: mm0ssmmm mm...mmm 1st parameter: mode + register or memory (as above) ...ss... 2nd parameter: segment register ...00... ES ...01... CS ...10... SS ...11... DS opcode extension form: mmooommm mm...mmm only parameter: mode + register or memory (as above) ..ooo... opcode extension, see description of instructions Instruction Code List: ---------------------- (full machine code bytes, in order: opcode number) 00rmd* ADD mb,rb 10rmd* ADC mb,rb 20rmd* AND mb,rb 30rmd* XOR mb,rb 01rmd* ADD mw,rw 11rmd* ADC mw,rw 21rmd* AND mw,rw 31rmd* XOR mw,rw 02rmd* ADD rb,mb 12rmd* ADC rb,mb 22rmd* AND rb,mb 32rmd* XOR rb,mb 03rmd* ADD rw,mw 13rmd* ADC rw,mw 23rmd* AND rw,mw 33rmd* XOR rw,mw 04nn ADD AL,n 14nn ADC AL,n 24nn AND AL,n 34nn XOR AL,n 05nnnn ADD AX,nn 15nnnn ADC AX,nn 25nnnn AND AX,nn 35nnnn XOR AX,nn 06 PUSH ES 16 PUSH CS 26 ES: 36 SS: 07 POP ES 17 POP SS 27 DAA 37 AAA 08rmd* OR mb,rb 18rmd* SBB mb,rb 28rmd* SUB mb,rb 38rmd* CMP mb,rb 09rmd* OR mw,rw 19rmd* SBB mw,rw 29rmd* SUB mw,rw 39rmd* CMP mw,rw 0Armd* OR rb,mb 1Armd* SBB rb,mb 2Armd* SUB rb,mb 3Armd* CMP rb,mb 0Brmd* OR rw,mw 1Brmd* SBB rw,mw 2Brmd* SUB rw,mw 3Brmd* CMP rw,mw 0Cnn OR AL,n 1Cnn SBB AL,n 2Cnn SUB AL,n 3Cnn CMP AL,n 0Dnnnn OR AX,nn 1Dnnnn SBB AX,nn 2Dnnnn SUB AX,nn 3Dnnnn CMP AX,nn 0E PUSH CS 1E PUSH DS 2E CS: 3E DS: 0F POP CS 1F POP DS 2F DAS 3F AAS *0|*1|*2|*3|*8|*9|*A|*B: rmd* means rm followed by 0|1|2 bytes displacement 0F: only on 8086/8088, from 80186/80186 on disabled 40 INC AX 50 PUSH AX 60 PUSHA 70dd JO d 41 INC CX 51 PUSH CX 61 POPA 71dd JNO d 42 INC DX 52 PUSH DX 62rm BOUND rw,mw 72dd JC/JB/JNAE d 43 INC BX 53 PUSH BX -- - 73dd JNC/JNB/JAEd 44 INC SP 54 PUSH SP -- - 74dd JZ/JE d 45 INC BP 55 PUSH BP -- - 75dd JNZ/JNE d 46 INC SI 56 PUSH SI -- - 76dd JBE/JNA d 47 INC DI 57 PUSH DI -- - 77dd JNBE/JA d 48 DEC AX 58 POP AX 68nnnn PUSH nn 78dd JS d 49 DEC CX 59 POP CX 69rmd*nIMUL rw,mw,n 79dd JNS d 4A DEC DX 5A POP DX 6Ann PUSH n 7Add JP/JPE d 4B DEC BX 5B POP BX 6Brmd*nIMUL rb,mb,n 7Bdd JNP/JPO d 4C DEC SP 5C POP SP 6C INSB 7Cdd JL/JNGE d 4D DEC BP 5D POP BP 6D INSW 7Ddd JNL/JGE d 4E DEC SI 5E POP SI 6E OUTSB 7Edd JLE/JNG d 4F DEC DI 5F POP DI 6F OUTSW 7Fdd JNLE/JG d 60|61|62|68|..|6F: unused in 8068/8088, added from 80186/80186 on 69|6B: rmd*n is rmd* displacem like in 00/etc, followed by 1|2 bytes constant 80omd*nim mb,n 90 XCHG AX,AX A0dddd MOV AL,[dd] B0nn MOV AL,n 81omd*nim mw,nn 91 XCHG AX,CX A1dddd MOV AX,[dd] B1nn MOV CL,n 82omd*nim mb,n 92 XCHG AX,DX A2dddd MOV [dd],AL B2nn MOV DL,n 83omd*nim mw,n 93 XCHG AX,BX A3dddd MOV [dd],AX B3nn MOV BL,n 84rmd* TEST rb,mb 94 XCHG AX,SP A4 MOVSB B4nn MOV AH,n 85rmd* TEST rw,mw 95 XCHG AX,BP A5 MOVSW B5nn MOV CH,n 86rmd* XCHG rb,mb 96 XCHG AX,SI A6 CMPSB B6nn MOV DH,n 87rmd* XCHG rw,mw 97 XCHG AX,DI A7 CMPSW B7nn MOV BH,n 88rmd* MOV mb,rb 98 CBW A8nn TEST AL,nn B8nnnn MOV AX,nn 89rmd* MOV mw,rw 99 CWD A9nnnn TEST AX,nnnn B9nnnn MOV CX,nn 8Armd* MOV rb,mb 9Adddd*CALLF ss:dd AA STOSB BAnnnn MOV DX,nn 8Brmd* MOV rw,mw 9B WAIT AB STOSW BBnnnn MOV BX,nn 8Csmd* MOV mw,rseg 9C PUSHF AC LODSB BCnnnn MOV SP,nn 8Drmd* LEA rw,mw 9D POPF AD LODSW BDnnnn MOV BP,nn 8Esmd* MOV rseg,mw 9E SAHF AE SCASB BEnnnn MOV SI,nn 8Fomd* POP mw 9F LAHF AF SCASW BFnnnn MOV DI,nn 80|81|82|83: o:im = 0:ADD 1:OR 2:ADC 3:SBB 4:AND 5:SUB 6:XOR 7:CMP n = 80|82: 1byte, 81: 2byte, 83: 1byte sign extended to 2byte 84|..|8F: rmd*|smd*|omd* are rm|sm|om and ev displacem like in 00/etc 8F: for POP mw allways o = 0 90: XCHG AX,AX is a NOP, used as official NOP instruction 9A: dddd* is ddddssss 2+2 bytes ss:dd segment+offset far address C0omd*nsh mb,n D0omd* sh mb,1 E0dd LOOPNZ/NE d F0 LOCK C1omd*nsh mw,n D1omd* sh mw,1 E1dd LOOPZ/E d -- - C2dddd RET dd D2omd* sh mb,CL E2dd LOOP d F2 REPNZ/NE C3 RET D3omd* sh mw,CL E3dd JCXZ d F3 REP/Z/E C4rmd* LES rw,mw D40A AAM E4pp IN AL,p F4 HLT C5rmd* LDS rw,mw D50A AAD E5pp IN AX,p F5 CMC C6rmd*nMOV mb,n D6 SALC E6pp OUT p,AL F6omd* un mb C7rmd*nMOV mw,nn D7 XLAT E7pp OUT p,AX F7omd* un mw C8nnnnlENTER nn,l D8omd* ESC 0o,mw E8dddd CALL dd F8 CLC C9 LEAVE D9omd* ESC 1o,mw E9dddd JMP dd F9 STC CAdddd RETF dd DAomd* ESC 2o,mw EAdddd*JMPF ss:dd FA CLI CB RETF DBomd* ESC 3o,mw EBdd JMP d FB STI CC INT 3 DComd* ESC 4o,mw EC IN AL,DX FC CLD CDnn INT n DDomd* ESC 5o,mw ED IN AX,DX FD STD CE INTO DEomd* ESC 6o,mw EE OUT DX,AL FEomd* gr mb CF IRET DFomd* ESC 7o,mw EF OUT DX,AH FFomd* gr mw C0|C1|C8:C9: unused in 8068/8088, added from 80186/80186 on C0|C1|D0|D1|D2|D3: o:sh = 0:ROL 1:ROR 2:RCL 3:RCR 4:SHL 5:SHR 7:SAR C0|C1: rmd*n is rmd* displacem like in 69|6B, followed by 1 byte constant C4|C5|D0|..|D3|F6|F7|FE|FF: rmd*|omd* is rm|om and ev displacem like in 00/etc C6|C7: rm allways r = 0, as source is immediate data C8: opcode followed by 2 byte constant offset and 1 byte constant level D4|D5: AAM/AAD are generalised mult|div constant for 0A->anything D6: SALC only got documented in P6 (Pentum Pro) docs, but is since 8086 D8|D..|DF: for 8087 FPU coprocessor, 64 0o..7o instructions omd* is om and ev displacem like in 00/etc EA: dddd* is ddddssss of 2+2 bytes ss:dd segment+offset far address F3: REP for INS|OUTS|MOVS|LODS|STOS, REPZ/E for CMPS|SCAS F6|F7: o:un = 0:TEST 2:NOT 3:NEG 4:MUL 5:IMUL 6:DIV 7:IDIV for 0:TEST followed by 1|2 bytes constant FE: o:gr = 0:INC 1:DEC FF: o:gr = 0:INC 1:DEC 2:CALLI 3:CALLIF 4:JMPI 5:JMPIF 6:PUSH Instruction Code Table: ----------------------- (only opcodes, in order: ver: bit7..6/5..3, hor: bit2..0) + 00 01 02 03 04 05 06 07 00 ADD mb, ADD mw, ADD rb, ADD rw, ADD AL, ADD AX, PUSH ES POP ES 08 OR mb, OR mw, OR rb, OR rw, OR AL, OR AX, PUSH CS POP CS 10 ADC mb, ADC mw, ADC rb, ADC rw, ADC AL, ADC AX, PUSH CS POP SS 18 SBB mb, SBB mw, SBB rb, SBB rw, SBB AL, SBB AX, PUSH DS POP DS 20 AND mb, AND mw, AND rb, AND rw, AND AL, AND AX, ES: DAA 28 SUB mb, SUB mw, SUB rb, SUB rw, SUB AL, SUB AX, CS: DAS 30 XOR mb, XOR mw, XOR rb, XOR rw, XOR AL, XOR AX, SS: AAA 38 CMP mb, CMP mw, CMP rb, CMP rw, CMP AL, CMP AX, DS: AAS 40 INC AX INC CX INC DX INC BX INC SP INC BP INC SI INC DI 48 DEC AX DEC CX DEC DX DEC BX DEC SP DEC BP DEC SI DEC DI 50 PUSH AX PUSH CX PUSH DX PUSH BX PUSH SP PUSH BP PUSH SI PUSH DI 58 POP AX POP CX POP DX POP BX POP SP POP BP POP SI POP DI 60 PUSHA POPA BOUND rw,- - - - - 68 PUSH w IMUL rw, PUSH b IMUL rb, INSB INSW OUTSB OUTSW 70 JO JNO JC JNC JZ JNZ JBE JA 78 JS JNS JP JNP JL JGE JLE JG 80 im mb,n im mw,nn im mb,n im mw,n TEST rb, TEST rw, XCHG rb, XCHG rw, 88 MOV mb, MOV mw, MOV rb, MOV rw, MOV ,rs LEA rw, MOV rs, POP mw 90 XCHG ,AX XCHG ,CX XCHG ,DX XCHG ,BX XCHG ,SP XCHG ,BP XCHG ,SI XCHG ,DI 98 CBW CWD CALLF WAIT PUSHF POPF SAHF LAHF A0 MOV AL,d MOV AX,d MOV d,AX MOV d,AX MOVSB MOVSW CMPSB CMPSW A8 TEST AL, TEST AX, STOSB STOSW LODSB LODSW SCASB SCASW B0 MOV AL, MOV CL, MOV DL, MOV BL, MOV AH, MOV CH, MOV DH, MOV BH, B8 MOV AX, MOV CX, MOV DX, MOV BX, MOV SP, MOV BP, MOV SI, MOV DI, C0 sh mb,n sh mw,nn RET dd RET LES rw, LDS rw, MOV mb,n MOV mw,nn C8 ENTER nn,LEAVE RETF dd RETF INT 3 INT INTO IRET D0 sh mb,1 sh mw,1 sh mb,CL sh mw,CL AAM AAD - XLAT D8 ESC 0y, ESC 1y, ESC 2y, ESC 3y, ESC 4y, ESC 5y, ESC 6y, ESC 7y, E0 LOOPNZ LOOPZ LOOP JCXZ IN AL, IN AX, OUT ,AL OUT ,AX E8 CALL JMP JMPF JMP IN AL,DX IN AX,DX OUT DX,ALOUT DX,AX F0 LOCK - REPNZ REP/REPZ HLT CMC un mb un mw F8 CLC STC CLI STI CLD STD gr mb gr mw