Assembly language is a low-level programming language for a computer or other programmable device specific to a particular computer architecture in contrast to most high-level programming languages, which are generally portable across multiple systems.
AX Accumulator - the accumulator register (divided into AH / AL).
BX Base - the base address register (divided into BH / BL).
CX Counter- the count register (divided into CH / CL).
DX Data - the data register (divided into DH / DL).
IP Instruction pointer - Current instruction offset
SP Stack pointer - Current stack offset
BP Base pointer - Base for referencing values stored on stack
SI Source index - General addressing, source offset in string ops
DI Destination index - General addressing, destination in string ops
CS Code segment - Segment to which IP refers
SS Stack segment - Segment to which SP refers
DS Data segment - General addressing, usually for program's data area
ES Extra segment - General addressing, destination segment in string ops
OF Overflow flag - Indicates a signed arithmetic overflow occurred
DF Direction flag - Controls incr. direction in string ops (0=inc, 1=dec)
IF Interrupt flag - Controls whether interrupts are enabled
TF Trap flag - Controls debug interrupt generation after instructions
SF Sign flag - Indicates a negative result or comparison
ZF Zero flag -Indicates a zero result or an equal comparison
AF Auxiliary flag - Indicates adjustment is needed after BCD arithmetic
PF Parity flag - Indicates an even number of 1 bits
CF Carry flag - Indicates an arithmetic carry occurred
Flag | OF | DF | IF | TF | SF | ZF | AF | PF | CF | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Bit | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
The syntax for storage allocation statement for initialized data is
[variable-name] define-directive initial-value
Directive | Explanation | Storage |
---|---|---|
DB | Define Byte | 1 Byte |
DW | Define Word | 2 Bytes |
DD | Define Doubleword | 4 Bytes |
DQ | Define Quadword | 8 Bytes |
DT | Define Ten Bytes | 10 Bytes |
var1 DB 'a'
var2 DB 25
var3 DW 693FH
var4 DD 12897F3CH
var5 DQ 123456789H
array DB 12,4,5,2,7,9,1,8 ; Byte type array
How can you read instruction set of 8086? First of all, no need to memorize the all instrucitons. When you need an instruction, you have to open the instruction set first.
DADDR -> Data memory address operands identified
RB -> Any one of the eight byte registers: AH. AL BH. BL CH. CL DH. or DL
RW -> Any one of the eight 16-bit registers: AX. BX. CX. DX. SP. BP. SI. or DI
EA -> Effective data memory address using any of the memory addressing options
Mnemonic | Operand(s) | Object Code | Clock Cycles | Operation Performed |
---|---|---|---|---|
MOV | RW,DADDR | 88 aadddbbb [DISP][DISP] | 8+EA | [RW] <- [EA] Load 16 bits of data from the data memory word addressed by DADDR to register RW |
ADD | RB,DADDR | 02 aadddbbb [DISP][DISP] | 9+EA | [RB] <- [EA] + [RB] Add the contents of the data byte addressed by DADDR to register RB |
MUL | AL,DADDR | F6 aa100bbb [DISP][DISP] | (76-83)+EA | [AX] <- [AL] • [EA] Multiply the 8-bit contents of register AL by the contents of the m~mory byte addressed by DADDR. Treat both numbers as unsigned binary numbers. Store the 16-bit product in AX |
Check out Instruction Set of 8086 for more
MOV − Used to copy the byte or word from the provided source to the provided destination.
MOV AL, FAH; Transfer the hexadecimal value FAH in AL register
MOV BL, 10110100b; Transfer the hexadecimal value 10110100b in BL register
MOV CX, 5; Transfer the octal value 5 in CX register
MOV AL, var1
MOV AH, AL
MOV Myvar, 12
Let AX : 4532H =
MOV Myvar, AX; [1001H] = AH = 45H
;[1002H] = AL = 32H
Memory Adress | Before MOV | After MOV |
---|---|---|
1003H | 4FH | 4FH |
1002H | 0ABH | 45H |
1001H Myvar -> | 53H | 32H |
1000H | 2CH | 2CH |
LEA - Loads offset address into the specified register.
LEA SI, Myvar ; SI = 1002H
Memory Adress | Value |
---|---|
1003H | 4FH |
1002H Myvar -> | 0ABH |
1001H | 53H |
1000H | 2CH |
XCHG - Exchanges the contents of the 16-bit or 8-bit specified register with the contents of AX register, specified register or memory locations.
MOV AX, 1234H; AX = 1234H
MOV BX, 1BCDH; BX = 1BCDH
XCHG AX, BX; AX = 1BCDH and BX = 1234H
ADD − Used to add the provided byte to byte/word to word.
SUB − Used to subtract the byte from byte/word from word.
MOV AL,0FEh; AL = 0FEh
ADD AL,1; AL = AL + 1 -> AL = 0FFh
SUB AL,1; AL = AL - 1 -> AL = 0FEh
INC − Used to increment the provided byte/word by 1.
DEC − Used to decrement the provided byte/word by 1.
MOV CX, 5; CX = 5
INC CX; CX = 6
DEC CX; CX = 5
MUL − Used to multiply unsigned byte by byte/word by word.
Type | Multiplied | Result |
---|---|---|
8 bit | AL | AX=[AH][AL] |
16 bit | AX | DX:AX=[DX][AX] |
32 bit | EAX | EAX=[EDX][EAX] |
The multiplicand is in the AL register, and the multiplier is a byte in the memory or in another register. The product is in AX. High-order 8 bits of the product is stored in AH and the low-order 8 bits are stored in AL.
MOV AL, 10
MOV DL, 25
MUL DL; AL x DL = [AH][AL]
The multiplicand should be in the AX register, and the multiplier is a word in memory or another register. For example, for an instruction like MUL DX, you must store the multiplier in DX and the multiplicand in AX.
MOV BX, 10
MUL BX; AX x BX = [DX][AX]
DIV − Used to divide the unsigned word by byte or unsigned double word by word.
MOV BH, 0F2H; Load numerator in BH
MOV AL, 4H; Load denominator in AL
DIV BH; Divide BH by AL
CMP - CMP is used to compare two operands and the value of the operands does not change as a result of the comparison. Only the result of the flag changes. Conditional branching instructions are used after the CMP.
Its simply does : operand1 - operand2 and you can see the result in the flags.
Condition | Signed Comparison | Unsigned Comparison |
---|---|---|
opr1 > opr2 | ZF = 0 | CF = 0 and ZF = 0 |
opr1 >= opr2 | SF= OF | CF = 0 |
opr1 = opr2 | ZF = 1 | ZF = 1 |
opr1 < opr2 | ZF = 1 | CF = 1 or ZF = 1 |
opr1 = opr2 | SF != OF | CF = 1 |
Conditional execution in assembly language is accomplished by several looping and branching instructions. These instructions can change the flow of control in a program.
Its like 'goto' statement in high level languages.
JMP - The JMP instruction provides a label name where the flow of control is transferred immediately.
In C:
int main() {
int i = 10;
goto Label1;
i = 55;
Label1:
printf("%d", i); // i = 10
}
In Assembly:
MOV AL, 10;
JMP Label1
MOV AL, 55;
Label1:
. ; AL = 10
.
.
This is performed by a set of jump instructions j depending upon the condition. The conditional instructions transfer the control by breaking the sequential flow and they do it by changing the offset value in IP. These instruction are used after the CMP.
Instruction | Operands | Condition |
---|---|---|
JZ/JE | opr1 - opr2 = 0 | ZF = 1 |
JNZ/JNE | opr1 - opr2 != 0 | ZF = 0 |
JS | opr1 - opr2 < 0 | SF = 1 |
JNS | opr1 - opr2 > 0 | SF = 0 |
JO | opr1 - opr2 = not between 127 and -128 | OF = 1 |
JNO | opr1 - opr2 = between 127 and -128 | OF = 0 |
JP/JPE | Even Parity | PF = 1 |
JNP/JPO | Odd Parity | PF = 0 |
JZ/JE - Jump if op1-op2 = 0 (ZF = 1)
JNZ/JNE - Jump if op1-op2 != 0 (ZF = 0)
MOV AL, 5
MOV BL, 5
CMP AL,BL; if statement
JZ zero; true statement(op1 = op2)
MOV CX, 10; false statement(op1 != op2)
JMP exit
zero: ;true statement
.
.
.
exit:
JS - Jump if op1-op2 < 0 (SF = 1)
JNS - Jump if op1-op2 > 0 (SF = 0)
MOV AL, 5
MOV BL, 10
CMP AL,BL; if statement
JS sign; true statement (op1 < op2)
MOV CX, 10; false statement(op1 > op2)
JMP exit
sign: ;true statement
.
.
.
exit:
JO - Jump if op1-op2 is not between 127 and -128
JNO - Jump if op1-op2 is between 127 and -128
MOV AL, -5
MOV DL, 127
CMP AL,DL; if statement (-5 - 127 = -132)
JO overflow; true statement
MOV BL,12; false statement
JMP exit
overflow: ; true statement
MOV CX,10
exit:
When comparing unsigned numbers, it is checked whether one value is above or below the other.
Instruction | Operands | Condition |
---|---|---|
JB/JNAE/JC | opr1 - opr2 < 0 | CF = 1 |
JA/JNBE | opr1 - opr2 > 0 | ZF = 0 and CF = 0 |
JAE/JNB/JNC | opr1 - opr2 >= 0 | CF = 1 |
JBE/JNA | opr1 - opr2 <= 0 | CF = 1 and ZF = 1 |
When comparing signed numbers, it is checked whether one value is greater or less than another.
Instruction | Operands | Condition |
---|---|---|
JL/JNGE | opr1 - opr2 < 0 | SF != OF and ZF = 0 |
JNL/JGE | opr1 - opr2 >= 0 | SF = OF |
JLE/JNG | opr1 - opr2 <= 0 | SF != OF and ZF = 1 |
JG/JNLE | opr1 - opr2 > 0 | SF = OF and ZF = 0 |
PUSH − Used to put a word at the top of the stack.
POP − Used to get a word from the top of the stack to the provided location.
MOV CX, 5; CX = 5
PUSH CX; CX = 5
INC CX; CX = 6
POP CX; CX = 5
In this method, the second operand is a number or ASCII value and operand types must be the same.
MOV AH, 06H; AH = 06H
MOV CX, 1FFCH; CX = 1FFCH
MOV AL, 'A'; AL = 41H
Both operands must be registers.
MOV AH, AL; AH = AL
MOV CX, AX; CX = AX
In direct addressing, the address of the operand is given as a label. This label can be defined as word or byte.
Let the value of myvar variable is 2F00H
Memory Block | Value |
---|---|
0004H | |
0003H | 2FH |
0002H myvar -> | 00H |
0001H |
If 'myvar' defined as a word
MOV AX, myvar; AX <- 2F00H
If 'myvar' defined as a byte
MOV AL, myvar; AL <- 00H
In register indirect adressing the address of the operand in memory is indicated by an index register.
Memory Block | Value |
---|---|
0004H | |
0003H | 4AH |
0002H <- myvar | 13H |
0001H | |
0000H |
LEA DI, myvar; DI <- 0002H
MOV AX, [DI]; AX <- 4A13H
In direct index adressing, memory addresses are accessed by an array.
Let the value of myvar variable is:
myvar DB 41H, 53H, 53H,45H, 4DH, 42H, 4CH, 59H ; Byte type variable
Memory Block | Value |
---|---|
0107H | 59H |
0106H | 4CH |
0105H | 42H |
0104H | 4DH |
0103H | 45H |
0102H | 53H |
0101H | 53H |
0100H myvar -> | 41H |
We can use SI, DI or BX registers as indices to access the myvar array. If we try to access the first value of the array
XOR SI,SI; SI -> 0000H
MOV AL, myvar[SI]; AL <- 41H
;If you try to access next value
INC SI; SI <- 0001H
MOV AH, myvar[SI]; AH <- 53H
If we can define myvar as word type
myvar DW 5341H,4553H, 424DH, 594CH; Byte type variable
Now we have to increase our index by two because now we have a word type array.
;If you increase index by one, you cant access the correct value.
XOR SI,SI; SI -> 0000H
MOV AX, myvar[SI]; AX <- 5341H
INC SI; SI -> 0001H
MOV AX, myvar[SI]; AX <- 5353H
;If you increase index by two.
XOR SI,SI; SI -> 0000H
MOV AX, myvar[SI]; AX <- 5341H
ADD SI, 2; SI -> 0002H
MOV AX, myvar[SI]; AX <- 4553H
https://www.tutorialspoint.com/assembly_programming/ https://www.javatpoint.com/instruction-set-of-8086