The 8086 is a 16-bit microprocessor ,released in 1978. The processor can address up to 1 M bytes of physical memory. Bytes and words are the fundamental data types (of 8086). A word is two contiguous bytes starting at any byte address. A word thus contains 16 bits. The bits of a word are numbered from 0 through 15; bit 0 is the least significant bit. The byte containing bit 0 of the word is called the low byte; the byte containing bit 15 is called the high byte. Each byte within a word has its own address, and the smaller of the addresses is the address of the word. The byte at this lower address contains the eight least significant bits of the word, while the byte at the higher address contains the eight most significant bits. "little-endian" Note that words need not be aligned at even-numbered addresses . 7 0 +---------------+ ¦ BYTE ¦ BYTE ( Byte Address = n ) +---------------+ address n 15 7 0 +-------------------------------+ ¦ HIGH BYTE ¦ LOW BYTE ¦ WORD ( Word Address = n ) +-------------------------------+ address n+1 address n 2.2 Registers The 8086 contains a total of sixteen registers that are of interest to the applications programmer. These registers may be grouped into : 1. General registers. These eight 16-bit general-purpose registers are used primarily to contain operands for arithmetic and logical operations. 2. Segment registers. These six registers determine, at any given time, which segments of memory are currently addressable. 3. Status and instruction registers. These special-purpose registers are used to record and alter certain aspects of the 8086 processor state. 2.2.1 General Registers The general registers of the 8086 are the 16-bit registers AX, BX, CX, DX, BP, SP, SI, and DI. These registers are used interchangeably to contain the operands of logical and arithmetic operations. AX = Accumulator Register BX = Base Register CX = Count Register DX = Data Register BP = Base Pointer SP = Stack Pointer SI = Source Index DI = Destination Index Each byte of the 16-bit registers AX, BX,CX, and DX has a separate name and can be treated as a unit. This feature is useful for handling characters and other 8-bit data items. The byte registers are named AH, BH, CH, and DH (high bytes); and AL, BL, CL, and DL (low bytes). The Source Index register usually denotes a pointer in memory where the pointer is the source of some data, whereas the Destination Index points to a destination. The stack is a place for temporary storage of data. When you push a value onto the stack, the value is saved into the place in memory where the Stack Pointer points to. The Stack Pointer is then decremented by the size of the value pushed, normally 16 bits = 2 bytes. The Stack Pointer should NOT ever be changed unless you know what you're doing and have a good reason. The Base Pointer generally means the lowest value that the Stack Pointer can reach. Just make sure that you don't use too much stack compared to what you've allocated. Especially beware of recursive functions. 2.2.2 Segment Registers The segment registers CS, DS, SS, and ES are used to identify current segments. Each register uniquely determines one particular segment ("code", "data", "stack", or "Extra"). The segment containing the currently executing sequence of instructions is known as the current code segment; it is specified by means of the CS register. All stack operations use the SS register to locate the stack. The DS and ES registers allow the specification of two data segments, each addressable by the currently executing program. Note that the segment registers are NOT implemented in the simulator. They all are set to 0000H in the simulator and can't be changed. 2.2.3 Flags Register The flags register is a 16-bit register. The flags control certain operations and indicate the status of the 8086. There are 9 basic flags... ODITSZAPC O -Overflow Flag D -Direction Flag I -Interrupt Flag T -Trap Flag S -Sign Flag Z -Zero Flag A -Auxiliary Carry Flag (or Adjust Flag) P -Parity Flag C -Carry Flag Overflow Flag changes when signed numbers are used in math commands. Set if result is too large a positive number or too small a negative number (excluding sign-bit) to fit in destination operand; cleared otherwise. For example, if 7F (+127 decimal) is added to 1 (+1 decimal), the result is 80 (-128 decimal). This represents an overflow. Interrupt Flag tells the CPU whether or not it can accept hardware interrupts through the INTR pin of 8086. If I is set, ie I = 1, it can accept HW interrupts. Otherwise cannot. Instruction STI is used to set I and CLI is used to clear I. Direction Flag tells the CPU to increment or decrement DI/SI registers on a LODSB, STOSB, MOVSB, and similar commands. Sign Flag is Set equal to high-order bit (the leftmost bit) of result (0 is positive, 1 if negative). Zero Flag is Set if result is zero; cleared otherwise. If Z=1, the result of the arithmetic or logic instruction is zero. If Z=0, the result is not zero. Carry Flag is Set on high-order bit carry or borrow; cleared otherwise. It holds the carry after addition, or borrow after subtraction. Parity Flag is Set if low-order eight bits of result contain an even number of 1 bits; cleared otherwise. Trap Flag is not implemented in the simulator. Auxiliary carry Flag is set when a half-carry is generated by bit 3 and passed to bit 4 in an arithmetic operation. This flag is used only by DAA and DAS instructions. 2.2.4 Instruction Pointer The instruction pointer register (IP) contains the offset address, relative to the start of the current code segment, of the next sequential instruction to be executed. The instruction pointer is not directly visible to the programmer; it is controlled implicitly by control-transfer instructions, interrupts, and exceptions. 2.3 Instruction Format An instruction has the following format: LABEL: MNEMONIC ARGUMENT1, ARGUMENT2 where: - A label is an identifier that is followed by a colon. - A mnemonic is a reserved name for a class of instruction opcodes that have the same function. It specifies the operation performed by the instruction. - The operands argument1, and argument2 are optional. There may be from zero to two operands, depending on the opcode. When two operands are present in an instruction that modifies data, the right operand is the source and the left operand is the destination. Operands can be register or memory locations. See below. For example: LOADREG: MOV AX, BX In this example LOADREG is a label, MOV is the mnemonic identifier of an opcode, AX is the destination operand, and BX is the source operand. Note that Only hexadecimal (Hex) numbers are used in the simulator. A hexadecimal digit is a character from the set (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F). That is they have a base of 16. That is , 1000, 1FFF, B000, C10D, are all hex. 2.4 Operand Selection An instruction can act on zero or more operands. An operand can be in any of these locations: - In the instruction itself (an immediate operand) - In a register AX, BX, CX, DX, SI, DI, SP, or BP in the case of 16-bit operands; AH, AL, BH, BL, CH, CL, DH, or DL in the case of 8-bit operands. - In memory Immediate operands and operands in registers can be accessed more rapidly than operands in memory since memory operands must be fetched from memory. Register operands are available in the CPU. Immediate operands are also available in the CPU, because they are prefetched as part of the instruction. 2.4.1 Immediate Operands Certain instructions use data from the instruction itself as one (and sometimes two) of the operands. Such an operand is called an immediate operand. The operand may be 16-, or 8-bits long. For example: ADD AX, 10 One byte of the instruction holds the value 10. 2.4.2 Register Operands Operands may be located in one of the 16-bit general registers (AX, BX, CX, DX, SI, DI, SP, or BP), or in one of the 8-bit general registers (AH, BH, CH, DH, AL, BL, CL or DL). MOV AX,BX MOV CX,DX MOV BL,DL MOV AH,CL MOV SI,DI Note that operands are equally-sized. 2.4.3 Memory Operands For memory operands , the memory address is calculated by taking the sum of up to three components: - A displacement element in the instruction. - A base register. (BX or BP) - An index register. (SI or DI) Following are the various data - addressing modes, related to memory: Direct Moves a byte or a word between a memory location and a register MOV [1234], AX ; move contents of ax to memory location 1234 MOV AX,[1000] ; move contents of memory location 1000 to AX 8086 cannot perform direct memory-to-memory transfer. You can also use other registers instead of AX; but that is a special addressing mode. Register Indirect Here the address of the memory operand is the contents of a base register or an index register. The offset that results is called an EFFECTIVE ADDRESS. MOV CL,[bx] ; memory address of source operand is the contents of BX INC BPTR [SI] ; increment byte at memory location [si] DEC WPTR [DI] ; decrement word at memory location [di] In the first example, if Bx has the value 1234 , then the memory address of the source operand is 1234 . The effective address here is 1234. Note that this is due to the fact that the segment registers are all assumed to be zero. Note the use of 'BPTR' and 'WPTR' in the other instructions. If only 'INC [SI]' is used, then the simulator will have no way of knowing whether [SI] points to a byte or a word in memory. It is up to the programmer. This is not needed in the first instruction, because the CL operand tells the simulator that a byte is addressed. Recall that both operands should be of the same type. BPTR - references a BYTE in memory WPTR - references a WORD in memory Base-plus-Index Here the sum of the contents of a base register and an index register is the effective address. MOV AX, [BX+SI] ADD [BX+DI], CX Register Relative Here the sum of the contents of either a base register and a displacement, or an index register and a displacement is the effective address. MOV DX, [BX + 20] MOV [SI + FF], AL MOV [DI + 10], BX Base-Relative plus Index Here the sum of the contents of a base register ,an index register and a displacement is the effective address. MOV CX, [BX + SI + 20] MOV [BX+ SI + FF], AL MOV [BX+ DI + 10], DX 2.5 Interrupts and Exceptions The 8086 has two mechanisms for interrupting program execution: 1. Exceptions are synchronous events that are the responses of the CPU to certain conditions detected during the execution of an instruction. 2. Interrupts are asynchronous events typically triggered by external devices needing attention. Interrupts and exceptions are alike in that both cause the processor to temporarily suspend its present program execution in order to execute a program of higher priority. The major distinction between these two kinds of interrupts is their origin. An exception is always reproducible by re-executing with the program and data that caused the exception, whereas an interrupt is generally independent of the currently executing program. The exceptions that may be of interest to applications programmers. - A divide error exception results when the instruction DIV or IDIV is executed with a zero denominator or when the quotient is too large for the destination operand. - A breakpoint exception results when the instruction INT 3 is executed. This instruction is used by some debuggers to stop program execution at specific points. - An overflow exception results when the INTO instruction is executed and the OF (overflow) flag is set (after an arithmetic operation that set the OF flag). The instruction INT generates an interrupt whenever it is executed; the processor treats this interrupt as an exception. The effects of this interrupt (and the effects of all other exceptions) are determined by exception handler routines provided by the application program or as part of the systems software (provided by systems programmers).INT instruction is explained in a later part. *********************************************************************** DB and DW Sometimes your program may need data tables. You can store them in your Memory and retrieved while running your program. An example data table is The seven segment led display codes in memory. You can store data within your Program using the .DB. and .DW. simulator directives. .DB. and .DW. stores Bytes or words in memory at the current location You can use .DB. or .DW. in two ways normally. One is at the start of the Program and the other is at the end. An example of .DB. at the start of the program JMP START DB 10,20,30,40 START: MOV AX,BX -------- -------- Here, data bytes 10,20,30, and 40 will be placed at memory locations 1003,1004,1005,1006 respectively. .Jmp. is needed at the start because .DB. is not an instruction. It will only assemble and not get simulated. Since .Jmp. takes 3 bytes of opcode, .DB. places data from 1003 onwards. *********************************************************************** Procedures A block of code that can be used repeatedly is written as a function. You can easily write a function as follows. PROC MYFUNC ------- ; instructions --------; instuctions RET You can use a function using the .CALL. instruction. CALL MYFUNC *********************************************************************** Interrupt Service Routines Advanced programming may need you to write ISRs.An ISR is written similar to a procedure, except that instead of any name, you have include the type of the ISR in its name. Also you must use .Iret. instead of .Ret.. PROC INT10 ------- ; instructions --------; instuctions IRet Here we have written an ISR for a type-10 interrupt. Note that you cannot use a name of your choice here. The name should be .int., where n is the type number.] *********************************************************************** Limitations -All instructions except the following (rarely used) are supported WAIT,LOCK,LDS,LES,ESC. -CS,SS,DS and ES are always zero. (0000H) You cannot change them in your program. Also, you cannot use instructions with references to these. That is why LES, LDS, MOV DS,AX etc are not supported. -Since it is wasteful to simulate the whole 1 MB, only 4KB of memory is simulated. The ram is from address 01000h to 01fffh.If you try to access any memory outside this range, it will show an error when executing. You can place your data in the address range 1000h-1fffh. Ex: mov ax,[1000] ; ok. mov [1fe3],bl ; ok mov [9FF],cl ; sorry. 9FF < 1000 mov [2000],bl ; sorry. 2000 > 1FFF mov al, [bx] ; depends on [Bx] -The program execution speed depends on your CPU speed. Thus, the simulator is not 'clocked' as in real 8086. The instruction execution times in real 8086 and the Simulator are not related. So you cannot use delays based on the clock cycles of instructions, in the simulator. However it will work correctly in real 8086. Note: the simulator always runs slower than real 8086. example: Mov CX,124 ; hex 124 CNTDN: Loop CNTDN A delay like the one above would take 1 millisec to execute on a real 8086(5 MHz) but takes about 10 millisec on the simulator.(P2-300) -The Trap Flag is not implemented