return to Choose a Color Scheme: Dark
Print Mode

Learn Multi platform 8086 Assembly Programming... For World Domination!

This page is Under Construction.... 'Learn 8086 is planned for 2020'

The 8086 was the sucessor to the 8080, from beginnings similar to the Z80, the 8086 was designed to set a foot into the 16 bit world!

In a 40 pin form and with segments to allow it to break out of the limits of a 16 bit address bus, the 8086 was the competitor to the 68000.... and while inferior in some ways - it was set to dominate the computing industry, blasting all it's rivals away, killing mighty giants like the PowerPC, the Sony CELL and even the ITANIUM! - only the highly efficient ARM processor today has managed to stand up to it's power!

Lets take a look at the beginnings of the 8086, and we'll also look a little at what was added to this chip, in the modern systems we use today!

In these tutorials we'll be looking at MS-DOS PC's, the WonderSwan and PC-98

If you want to learn 8086 get the Cheatsheet! it has all the 8086 commands, It will help you get started with ASM programming, and let you quickly look up commands when you get confused!

We'll be using USAM as our assenbker for these tutorials
You can get the source and documentation for UASM from the official website HERE

What is the 8086 and what are 16 'bits' You can skip this if you know about binary and Hex (This is a copy of the same section in the Z80 tutorial)
The 8086 is an 16-Bit processor with a 20 bit Address bus... though actually the Address bus and Data bus share the same pins on the CPU!
The 8088 is the same as the 8086, but it only has an 8 bit data bus... this makes it slower, but it makes no difference to our programs!

What's 8 bit... well, one 'Bit' can be 1 or 0
four bits make a Nibble (0-15)
two nibbles (8 bits) make a byte (0-255)
two bytes (16 bits) make a word (0-65535)

And what is 65535? well that's 64 kilobytes ... in computers Kilo is 1024, because four bytes is 1024 bytes
64 kilobytes is the amount of memory a basic 8-bit system can access

You probably think 64 kilobytes doesn't sound much when a small game now takes 8 gigabytes, but that's 'cos modern games are sloppy, inefficient,  fat and lazy - like the basement dwelling losers who wrote them!!!
6502 code is small, fast, and super efficient - with ASM you can do things in 1k that will amaze you!

Numbers in Assembly can be represented in different ways.
A 'Nibble' (half a byte) can be represented as Binary (0000-1111) , Decimal (0-15) or  Hexadecimal (0-F)... unfortunately, you'll need to learn all three for programming!

Also a letter can be a number... Capital 'A'  is stored in the computer as number 65!

Think of Hexadecimal as being the number system invented by someone wit h 15 fingers, ABCDEF are just numbers above 9!
Decimal is just the same, it only has 1 and 0.

In this guide, Binary will shown with a % symbol... eg %11001100 ... hexadecimal will be shown with & eg.. &FF.

Assemblers will use a symbol to denote a hexadecimal number, some use $FF or #FF or even 0x, but this guide uses & - as this is how hexadecimal is represented in CPC basic
All the code in this tutorial is designed for compiling with WinApe's assembler - if you're using something else you may need to change a few things!
But remember, whatever compiler you use, while the text based source code may need to be slightly different, the compiled "BYTES' will be the same!
Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ... 255
Binary 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111   11111111
Hexadecimal 0 1 2 3 4 5 6 7 8 9 A B C D E F   FF

Another way to think of binary is think what each digit is 'Worth' ... each digit in a number has it's own value... lets take a look at %11001100 in detail and add up it's total

Bit position 7 6 5 4 3 2 1 0
Digit Value (D) 128 64 32 16 8 4 2 1
Our number (N) 1 1 0 0 1 1 0 0
D x N 128 64 0 0 8 4 0 0
128+64+8+4= 204            So %11001100 = 204 !

If a binary number is small, it may be shown as %11 ... this is the same as %00000011
Also notice in the chart above, each bit has a number, the bit on the far right is no 0, and the far left is 7... don't worry about it now, but you will need it one day!

If you ever get confused, look at Windows Calculator, Switch to 'Programmer Mode' and  it has binary and Hexadecimal view, so you can change numbers from one form to another!
If you're an Excel fan, Look up the functions DEC2BIN and DEC2HEX... Excel has all the commands to you need to convert one thing to the other!

But wait! I said a Byte could go from 0-255 before, well what happens if you add 1 to 255? Well it overflows, and goes back to 0!...  The same happens if we add 2 to 254... if we add 2 to 255, we will end up with 1
this is actually usefull, as if we want to subtract a number, we can use this to work out what number to add to get the effect we want

Negative number -1 -2 -3 -5 -10 -20 -50 -254 -255
Equivalent Byte value 255 254 253 251 246 236 206 2 1
Equivalent Hex Byte Value FF FE FD FB F6 EC CE 2 1

All these number types can be confusing, but don't worry! Your Assembler will do the work for you!
You can type %11111111 ,  &FF , 255  or  -1  ... but the assembler knows these are all the same thing! Type whatever you prefer in your ode and the assembler will work out what that means and put the right data in the compiled code!

FRPCart, so EAX,EBX,ECX, EDX... and EBP,ESP,ESI,EDI... also more data segments were added, after DS and ES, we have FS and GS

Later machines like the Pentium III and x64 added more registers... but we're not covering them here!

Special Memory addresses on the 8086
From To Meaning
$000000 $00007F Reserved
$000080 $FFFFEF General Ram
$FFFFF0 $FFFFFF Reserved

The 8086 Addressing Modes
The 6502 has 11 different addrssing modes... many have no comparable equivalent on the Z80
Mode Description Sample Command Valid Registers Z80 Equivalent effective result
Register An 8 or 16 bit registter -
Immediate A constant value
Direct Memory A fixed location in memory
Register indirect Contents of register [BX], [BP], [DI], [SI]
Base or index Contents of register plus displacement d+[BX], d+[BP], d+[DI], d+[SI]
Base plus index Contents of base register plus contents of index register mov ax, [bx+di] 
mov ax, [bx+si] 
mov ax, [bp+di]
mov ax, [bp+si]
[BX][DI], [BX][SI],
[BP][DI], [BP][SI]
Base plus index with
Sum of base register, index register, and displacement mov ax, table[bx][di]
mov ax, table[di][bx]
mov ax, table[bx+di]
mov ax, [table+bx+di]
mov ax, [bx][di]+table
IO Port Addressing

RESB 1 allocates 1 byte.

RESW 1 allocates 2 bytes.

RESD 1 allocates 4 bytes.

RESQ 1 allocates 8 bytes.

BYTE, DB (byte) Allocates unsigned numbers from 0 to 255.
SBYTE (signed byte) Allocates signed numbers from –128 to +127.
WORD, DW (word = 2 bytes) Allocates unsigned numbers from 0 to 65,535 (64K).
SWORD (signed word) Allocates signed numbers from –32,768 to +32,767.
DWORD, DD (doubleword = 4 bytes),  Allocates unsigned numbers from 0 to 4,294,967,295 (4 megabytes).
SDWORD (signed doubleword) Allocates signed numbers from –2,147,483,648 to +2,147,483,647.
FWORD, DF (farword = 6 bytes) Allocates 6-byte (48-bit) integers. These values are normally used only as pointer variables on the 80386/486 processors.
QWORD, DQ (quadword = 8 bytes) Allocates 8-byte integers used with 8087-family coprocessor instructions.
TBYTE, DT (10 bytes),  Allocates 10-byte (80-bit) integers if the initializer has a radix specifying the base of the number.

mov ax, nearvar ; Reads from DS:[nearvar]
mov di, [bx] ; Reads from DS:[bx]
mov [di], cx ; Writes to DS:[di]
mov [bp+6], ax ; Writes to SS:[bp+6]
mov bx, [bp] ; Reads from SS:[bp]

Learn Assembly for the Greatest Classic Processors:  Z80 - 6502 - 68000
Visit to get my games and their source code! | Support me on patreon