/assembly-things

Some stuffs about low level programming

Primary LanguageAssembly

Hello 8086 Assembly

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.

alt text

General Registers

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).

Offset Registers

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

Segments

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

Flags

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

alt text

Variables

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

8086 Instructions

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

Data Transfer Instructions

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

Arithmetic Instructions

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]
When two bytes are multiplied
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]
When two one-word values are multiplied
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

Branch Instructions

Conditional execution in assembly language is accomplished by several looping and branching instructions. These instructions can change the flow of control in a program.

Unconditional Branch Instructions

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
    .
    .

Conditional Branch Instructions

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:  

Conditional branching instructions used with unsigned numbers

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

Conditional branching instructions used with signed numbers

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

Stack Instructions

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

Adressing Methods

Immediate Adressing

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

Register Adressing

Both operands must be registers.

MOV AH, AL; AH = AL
MOV CX, AX; CX = AX

Direct Adressing

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

Register Indirect Adressing

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

Direct Index Adressing

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

Sorting Algorithms

References

https://www.tutorialspoint.com/assembly_programming/ https://www.javatpoint.com/instruction-set-of-8086