The code snippets are in armasm because x86asm wouldn’t render. So ignore the syntax errors.
Emu8086
Registers
Memory slots used to store data
General Purpose Registers
- ax - the accumulator register (divided into ah / al)
- bx - the base address register (divided into bh / bl)
- cx - the count register (divided into ch / cl)
- dx - the data register (divided into dh / dl)
- si - source index register
- di - destination index register
- bp - base pointer
- sp - stack pointer
Segment Registers
- cs - points at the segment containing the current program
- ds - generally points at the segment where variables are defined
- es - extra segment register, it’s up to the programmer to define its usage
- ss - points at the segment containing the stack
All general purpose registers are 16 bit
In the 8086 assembly language, there are several registers, each serving a specific purpose. Here’s a brief description of each register and its typical usage:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
General-Purpose Registers:
AX (Accumulator): Used for arithmetic and data manipulation. It is also involved in some multiplication and division operations.
BX (Base): Often used as a pointer to data or an offset in memory addressing.
CX (Count): Primarily used as a loop counter in iterative operations.
DX (Data): Like AX, it is used for arithmetic operations and sometimes holds the high-order bits of the result.
Segment Registers:
CS (Code Segment): Points to the current code segment.
DS (Data Segment): Points to the data segment where program variables are stored.
SS (Stack Segment): Points to the stack segment, which holds the program stack.
ES (Extra Segment): Used to store additional data segment addresses.
Index and Pointer Registers:
SI (Source Index): Typically used as a pointer to the source data in string operations.
DI (Destination Index): Usually used as a pointer to the destination in string operations.
BP (Base Pointer): Frequently used to access function parameters and variables stored on the stack.
SP (Stack Pointer): Points to the top of the stack and is involved in managing the stack.
Flags Register:
FLAGS: Contains various status flags indicating the outcome of arithmetic and logical operations, as well as control flags for branching and looping.
These registers are fundamental to 8086 assembly programming, and their usage may vary depending on the specific requirements of a program.
Data Types
- db - Define Byte
- dw - Define Word
- dd - Define Doubleword
- dq - Define Quadword
Examples
1
2
3
a db 9
message db 'hello world'
var dw 1122h ; hexadecimal value
1
2
string db "lorem ipsum", '$' ; '$' for end of string
string1 db 10, 13, "lorem ipsum", '$' ; 10,13 for new line
Arrays
Declaration
1
a db 1h, 2h, 3h, 7h ; int a[] = {1, 2, 3, 7}
1
2
3
4
5
6
; Store a value from an array to the al register
mov al, a[2]
; or with the help of the index rsgister
mov si, 2
mov al, a[si]
Array Declaration using DUP
1
2
3
4
5
x db 3 dup(7)
; same as
x db 7, 7, 7
1
2
3
4
5
y db 3 dup(5, 6)
; same as
y db 5, 6, 5, 6, 5, 6
Declaring an empty array
1
var db 10 dup(?) ; int var[10] = {0}
MOV instruction
It copies the second operand, called source, to the first operand called destination
1
mov ax, 7
Types of operands supported
1
2
3
4
5
6
7
8
9
10
11
;reg: ax, bx, ah, al, ch, cl, cx, di...etc
;immediate: 7, -11, 4fh...etc
;memory: [bx] or [bx+si] + displacement
mov reg, memory
mov memory, reg
mov reg, reg
mov memory, immediate
mov reg, immediate
;note -> mov memory, memory is not supported
Memory
Combination of bx, si, di, bp registers inside of [] can be used to access memory
ADD
1
2
3
mov ax, 11h
mov bx, 14h
add ax, bx ; ax = 25h
The result is stored in the destination (first register)
SUB
1
2
mov ch, 23h
sub ch, 11h ; now ch = 12h
Flags or Processor Status Registers
16 bits. Each bit is called a “flag” and can be 0 or 1
- Carry Flag: Set to 1 when there is unsigned overflow
- Zero Flag: Set to 1 when result is zero, else it is set to 0
- Sign Flag: Set to 1 when the result is negative, else it is set to 0
Example
1
2
mov ch, 12h
sub ch, 24h
Flags: Z = 0 (result not zero), C = 1 (carry), S = 1 (result negative)
MUL
Multiplication assumes one of the operands is al or ax.
1
2
3
4
mov al, 7h
mov bl, 7h
mul bl
The result is stored in the al or ax register
IMUL
It’s used for signed numbers
1
2
3
4
mov al, 35h
mov bl, 7h
imul bl
IMUL uses the overflow flag
DIV
The result is stored in the al and ah registers respectively and div assumes one of the operands is ax.
1
2
3
4
mov ax, 0041h
mov bl, 02h
div bl
ax
(41) / bl
(2) = al
(20) + ah
(1)
IDIV
It’s used for unsigned numbers
Logical Intructions
- AND
- OR
- XOR
- NOT
- TEST
Using AND to determine if a number is even or odd
It changes the value of the al register
1
2
mov al, 8h
and al, 01h
0000 1000
0000 0001
===AND===
0000 0000
So the number is even
1
2
mov al, 5h
and al, 01h
0000 0101
0000 0001
===AND===
0000 0001
So the number is odd
TEST
Like AND
It does not change the value of the al register
1
2
3
mov al, 7h
test al, 01h
; affects the flag
The other operands work as expected
Program Control Flow
Jumps
jmp, je, jle, jne, jz, jnz, ja, jb, jc
Unconditional Jumps
They transfer control to another part of the program
Sample code
1
jmp read ;jump to read label
1
2
3
4
5
6
7
read:
mov ah, 01
jmp exit
exit:
mov ah, 4ch
int 21h
Conditional Jumps
- Jump only when some condition is satisfied
- Most jumps work by affecting CPU FLAGs while jumps like jcxz depend on the register
je
and jz
- Jump when ZERO flag is equal to 1. They are more appropriate when you check whether something is 0 or not
jne
and jnz
- Jump when ZERO flag is 0. They are mostly used after a cmp instruction
ja
and jg
- Jump if above jump is greater
ja
- Jump if CF = 0 and ZF = 0
jg
- Jump if SF = OF and ZF = 0
jb
- Jump if CF = 1
jc
- Jump if CF = 1
jcxz
- Jump id CX register is zero
Instructions
inc
- Adds 1 to any registerdec
- Subtracts 1 from any registercmp
- subtract source form destination and set the flags appropriately
1
2
3
inc ax
dec bx
cmp al, 10h
Bit Manipulation
shl
- Shifts bits of byte to the left.
1
shl al, 1 ; shift al by 1 (use cl register if it's more than 1)
shr
- Shifts bits of byte to the right
1
shr al, 1 ; shift al by 1 (use cl register if it's more than 1)
rol
- Rotates the bits from the front to the back
1
2
mov cx, 7h
rol ax, cl ; requires immidiate 8 bit operand or the cl register as the shift count
ror
- Rotates the bits from the back to the front
1
2
mov cx, 7h
ror ax, cl ; requires immidiate 8 bit operand or the cl register as the shift count
Standard code snippets
Assume segment registers
1
assume cs: code, ds: data, ss:stack
Initalize ds
1
2
mov ax, data
mov ds, ax
Return control to OS
1
2
mov ah, 4ch
int 21h
Print string
1
2
3
lea dx, msg
mov ah, 9
int 21h
Print integer
1
2
3
4
mov dl, int
add dl, 48
mov ah, 2
int 21h
Get integer / character input
Gets the ascii value
1
2
mov ah, 8h
int 21h
Get integer / character input and print it
Gets the ascii value
1
2
mov ah, 1
int 21h
Software interrupts
Before int 21h
- “Terminate program” - AH = 4Ch (76 decimal)
- “Display string” - AH = 09h (9 decimal)
- “Read keyboard input” - AH = 01h (1 decimal)
- “Write character to standard output” - AH = 02h (2 decimal)
- “Get system date” - AH = 2Ah (42 decimal)
- “Get system time” - AH = 2Ch (44 decimal)
- “Create a new file” - AH = 3Ch (60 decimal)
- “Open an existing file” - AH = 3Dh (61 decimal)
- “Close a file” - AH = 3Eh (62 decimal)
- “Read data from a file” - AH = 3Fh (63 decimal)
- “Write data to a file” - AH = 40h (64 decimal)
- “Delete a file” - AH = 41h (65 decimal)
- “Rename a file” - AH = 56h (86 decimal)
- “Get current disk drive” - AH = 19h (25 decimal)
- “Set disk transfer area address” - AH = 1Dh (29 decimal)
- “Get system time count” - AH = 2Dh (45 decimal)
- “Set system time” - AH = 25h (37 decimal)
- “Get current default drive” - AH = 19h, DL = 0 (25 decimal, DL = 0)
Processes
1
2
3
4
5
6
[name] proc
...
...
...
ret
[name] endp
Template file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
title [title]
assume cs:code, ds:data, ss:stack
stack segment stack
db 256 dup(0)
stack ends
data segment
; data
data ends
code segment
main proc near
mov ax, data
mov ds, ax
mov ah, 4ch
int 21h
main endp
code ends
end main
Printing numbers
2 digits
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
print_two_digit_num proc
push bx
push cx
; assuming number is in ax
mov cl, 10
div cl ; ax / cl -> ah, al
mov bx, ax
mov dl, bl
add dl, 48
mov ah, 2
int 21h
mov dl, bh
add dl, 48
mov ah, 2
int 21h
pop bx
pop cx
ret
print_two_digit_num endp
3 digits
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
print_three_digit_num proc
push bx
push cx
mov cl, 100
div cl
mov bx, ax
mov dl, bl
add dl, '0'
mov ah, 2h
int 21h
xchg bl, bh
mov bh, 0
mov ax, bx
mov cl, 10
div cl
mov bx, ax
mov dl, bl
add dl, '0'
mov ah, 2h
int 21h
mov dl, bh
add dl, '0'
mov ah, 2h
int 21h
pop bx
pop cx
ret
print_three_digit_num endp