These tutorials focus on the 8086, but also discuss the 186 and later x86 cpus
Resources 8086 reference manual - Detailed but to the point reference manual MASM programimng guide - We use UASM, but it's MASM compatible! UASM - the x86 assembler used by these tutorials (free and open source!) Platforms covered in this series MS-Dos based IBM PC Wonderswan / Wonderswan Color ChibiAkumas Tutorials
Absolute Beginners series (Terminology and concepts)
|
Lesson M1 - Random Numbers and Ranges [DOS] |
Lesson M2 - Binary Coded Decimal |
Lesson H1 - Hello World on MS Dos |
Lesson H2 - Hello World on the WonderSwan / Wonderswan Color |
Lesson H3 - Hello World on MS Dos via Native Tools (MASM 6.11) [DOS] |
Lesson S1 - Sprite drawing and Simple key movement in MS DOS |
Lesson S2 - Sprite drawing and Simple key movement on the Wonderswan |
The
8086 is pretty old now, but it's the basis of all the
computers we have today... With the 8086, We can learn about the fundamentals of computing and we can have some fun along the way! |
Base |
Type |
symbol |
Alternate |
2 | Binary |
10101010b | |
8 | Octal |
777o | 777q |
10 | Decimal |
100 | 100d |
16 | Hex |
0FFh | 0xFF |
The
symbols used to denote numbers vary between assemblers, in
these 8086 tutorials we use UASM, and --h is used for
hexadecimal, eg 0FFh, and ---b for binary, eg 1010b If your not using UASM, you many need something different! |
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 |
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 your maths sucks and you
can't figure it out, 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! |
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 0b11111111 , 0xFF , 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! |
Main
Registers:
String commands Copy DS:SI to ES:DI Segment Registers:
The Registers are 16 bit, but the address bus is 20 bit... these 'Segment registers' are added to the top 20 bits of the address eg: ----DDDDDDDDDDDDDDDD ... D=DX EEEEEEEEEEEEEEEE---- ... E=ES |
Flags: ----ODIT
SZ-A-P-C
|
There are some special addressing ranges you'll want to know about... |
|
Interrupt | From | Purpose |
0 - Div0 | 0000/1 | IP - Offset |
0002/3 | CS - Segment | |
1 - Step Trap | 0004/5 | IP - Offset |
0006/7 | CS - Segment | |
2 - NMI | 0008/9 | IP - Offset |
000A/B | CS - Segment | |
3 - 1 byte INT | 000C/D | IP - Offset |
000E/F | CS - Segment | |
4
- Sign Overflow |
0010/1 | IP - Offset |
0012/3 | CS - Segment | |
5 - reserved | 0014/5 | IP - Offset |
0016/7 | CS - Segment | |
reserved | ... | ... |
31 -reserved | 007C/D | IP - Offset |
007E/F | CS - Segment |
Mode | Description | Sample Command | Valid Registers |
Register Addressing | An 8 or 16 bit register | mov ax,bx mov al,bl |
- |
Immediate Addressing | A constant value | mov ax,100 | |
Direct Memory Addressing | A fixed location in memory | mov ax,[1000h] INC BYTE PTR [MyData] |
We may need to specifiy WORD PTR [label] |
Register indirect Addressing | Contents of register used as an address | mov ax,[bx] | [BX], [BP], [DI], [SI] |
Based or Indexed Addressing | Contents of register (Base or Index) plus displacement | mov ax,[bx+4] | d+[BX], d+[BP], d+[DI], d+[SI] |
Based, Indexed Addressing | 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] |
Based, Indexed Addressing with displacement | 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 |
d+[BX][DI], d+[BX][SI], d+[BP][DI], d+[BP][SI] |
String Addressing | String commands. | MOVSB MOVSW |
Src = DS:SI Dest = ES:DI |
If we want to read from an address specified by label we must
specify the size of the data we want to read from the address...
there are 3 commands we can use: BYTE PTR - Load a byte WORD PTR - Load a Word DWORD PTR - Load a DoubleWord (386+) |
SomeData: dw 1234h ;2 bytes of data mov ax,WORD PTR [cs:somedata] ;This will work mov ax,[cs:008Ch] ; if somedata=008Ch this will work mov ax,[cs:somedata] ;This will NOT work |
Set Trap Flag | Command to set trap flag (preserves other flags) | pushf mov bp,sp or word ptr [bp],0100h ; Set Trap flag (T) popf |
Set Trap Flag Quick | Command to set trap flag | mov ax,0100h
;Clear the trap flag (T) push ax popf |
Clear Trap Flag | Command to clear trap flag (preserves other flags) | popf mov bp,sp and word ptr [bp],0FEFFh ; Clear Trap flag (T) popf |
Clear Trap Flag Quick | Command to clear trap flag | mov ax,0000h
;Clear the trap flag push ax popf |
Bytes | Z80 | 68000 | 8086 | ARM |
1 |
DB | DC.B | DB | .BYTE |
2 |
DW | DC.W | DW | .WORD |
4 |
DC.L | DD | .LONG | |
n |
DS | DS | DUP | .SPACE |
Type | Defined by | Example |
Hexadecimal | 0x | #0xFF |
Deximal | #255 | |
Binary | 0b | #0b11110000 |
We're going to be using UASM
as an assembler, it's a free Microsoft MASM assembler which
works on windows, OSX and Linux My Devtools provide a batch file which will build the programs for you, but if you don't want to use them, the format of the build script is shown below: -mz ... Specifies to create DOS EXE File -Dxxx=Y ... Specifies to define a symbol xxx=y (we'll learn about symbols later. -Fl ... Specifies a Listing file - this shows source code and resulting bytes... it's used for debugging if we have problems -Fo ... Specifies the output file. %BuildFile%... this would be the sourcefile you want to compile... Eg: Lesson1.asm |
|
Once we've successfully compiled our program, we'll run it with
DOSBOX If we want the program to start automatically we'll need to add a few extra lines to the dosbox.conf |
There's a lot of
complex scary stuff in the include files - don't panic about it
for now, you'll be able to understand it more later once you've
covered all the lessons. |
Lets look at another subroutine. This one stars with a label 'DoMonitorAXBX'... we know it's a label because it's not indented and ends in a colon... this is the name of the subroutine - we'll see the name with call statements. Then there are 3 Calls... these are indented, so they are clearly commands... because Calls return after running, first subroutine 'DoMonitorAX' will occur, then 'DoMonitorBX', then 'Newline' Finally there is a RET command - this ends a subroutine... RETurning back to the CALL statement that started it. if our code has a RET at the end - it's a subroutine and should probably be started with a CALL... if we start it with a JMP something bad will probably happen! |
There may be times you see
code do weird things with CALL,JMP and RET statements that
aren't as simple as this... Don't worry about it for now - It's to complex for you right now... but don't worry, soon you to will be able to wield awesome ASM power! |
AX
isn't the only register we can do this with... we also have
BX,CX and DX... There's other registers like DI and SI - but these can't be split into 8 bit parts - they are for 'special purposes' |
Lesson 1is over!... What we've covered here may
seem confusing - and it may be a little disappointing! If you don't understand what you've seen, then try changing some of the values and writing your own commands, it should be more clear... If you don't see how this can help you write games... don't worry, you need to understand a lot of commands - but they'll soon build up and it will be more clear. |
WE also looked at this before as well - 'Register Addressing' is where both source and destination parameters of a command are registers |
|
Here is the results |
We've used positive base
pointers here, but we can use negative ones too! Unlike the Z80, On the 8086 the displacement can be an 8 or 16 bit number! |
Beware...
these kind of commands only work with BX+DI, BX+SI, BP+DI,
BP+SI... Whats worse, the assembler won't warn you if you're being stupid and trying to use them - the code won't work... so be careful, or you'll waste hours trying to work out why your code isn't working! |
We've
covered a lot of different addressing modes here very
quickly... you may be confused which registers can be used in
which modes -and when you can use them... The best thing is to give it a go! Try changing the examples and see what works, and what doesn't! |
Name | Meaning | Command to set Flag |
Command to clear Flag |
|
T | Trap | 1=Cause INT2 every instruction |
||
D | Direction | Used for 'string' cunctions |
STD | CLD |
I | Interrupt enable | Allow maskable hardware interrupts |
STI | CLI |
O | Overflow | 1=Overflow (sign changed) |
||
S | Sign | 1=Negative 0=positive (top bit of reg) |
||
Z | Zero | 1=Zero |
||
A | Aux carry | Used as Carry in BCD |
||
P | Parity | 1=Even no of 1 bits (8 bit) |
||
C | Carry | 1=Carry/Borrow caused by last ADD/SUB/ROT instruction |
STC (see CMC) | CLC |
Don't
worry about all the flags at this stage, - ones like Trap
Direction and Interrupt are not relevant to conditions You won't need them in this example, and depending on the commands you use, you may not need to! |
Command |
Details |
Flags |
JA / JNBE short-label | (Unsigned) above/not below nor equal | (CF AND ZF)=O |
JBE / JNA short-label | (Unsigned) below or equal/ not above | (CF OR ZF)=1 |
JC / JB / JNAE short-label | (Unsigned) carry/below / not above nor equal | CF=1 |
JCXZ short-label | Jump If CX Zero (see loop) | |
JE / JZ short-label | equal/zero | ZF=1 |
JG / JNLE short-label | (Signed) greater/ not less nor equal | ((SF XOR OF) OR ZF)=O |
JGE / JNL short-label | (Signed) greater or equal/not less | (SF XOR OF)=O |
JLE / JNG short-label | (Signed) less or equal/ not greater | ((SF XOR OF) OR ZF)=1 |
JL / JNGE short-label | (Signed) less/not greater nor equal | (SF XOR OF)=1 |
JMP target | Jump to label (byte or word target) | |
JNC / JAE / JNB short-label | (Unsigned) above or equal/ not below | CF=O� AX>=cmp |
JNE / JNZ short-label | not equal/ not zero | ZF=O |
JNO short-label | not overflow | OF=O |
JNP / JPO short-label | not parity / parity odd | PF=O |
JNS short-label | not sign | SF=O |
JO short-label | overflow | OF=1 |
JP / JPE short-label | parity/ parity equal (bits 0-7 only) | PF=1 |
JS short-label | sign | SF=1 |
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 |
We can also test the sign bit - if the top bit of the last
mathematical operation is 0 then the value is positive - if it's 1
then the value is negative. the S bit will be set if the result is <0 |
|
The Parity bit is a bit odd... The 1 bits are summed in the first byte... if there's an odd number P=0 (odd)... if there's an even number P=1 (even) | |
We've looked at a
large variety of commands here - but you REALLY need to try them
yourself before they'll make sense. The example code above had many alternate test REMmed out - try unremming them! |
'Stacks' in assembly are like an
'In tray' for temporary storage... Imagine we have an In-Tray... we can put items in it, but only ever take the top item off... we can store lots of paper - but have to take it off in the same order we put it on!... this is what a stack does! If we want to temporarily store a register - we can put it's value on the top of the stack... but we have to take them off in the same order... The stack will appear in memory, and the stack pointer goes DOWN with each push on the stack... so if it starts at $2000 and we push 2 bytes, it will point to $1FFE on the 8086 we push bytes into the stack in pairs |
Today
example has a lot of 'tricks' we wont cover today that allow
the stack to be shown to the screen - normally a call would
use the stack But we're using a fake stack so that only the push pop commands affect the shown stack - this is to allow the shown stack to only show the effect of the example commands - not the stack and register dump routines |
You
have to be careful to remove everything your subroutine put on
the stack before the return... otherwise the RET command will
mistake one of your pushed values for the return address and
run something crazy! DON'T SAY I DIDN'T WARN YOU!... but if you're super clever you can take advantage of things like this to do clever stuff! |
The RET command on the 8086 has a special trick... after the
return it can pop a number of bytes of the stack... The reason for this is it's common to push parameters onto the stack before calling a function - the function will use those parameters, and this is a way of removing them. In this example we'll push 4 bytes (2 words) onto the stack, and the function will load them to CX and DX, then return... The RET statement will remove the 4 bytes |
|
CX and DX will receive the values pushed on to the stack |
Command | Destination register | Parameter | Result |
AND | 1 0 1 0 |
1 1 0 0 |
1 0 0 0 |
OR | 1 0 1 0 |
1 1 0 0 |
1 1 1 0 |
XOR | 1 0 1 0 |
1 1 0 0 |
0 1 1 0 |
NOT | 1 0 |
0 1 |
Command | mov al,0b10101010 xor al,0b11110000 |
mov al,0b10101010 and al,0b11110000 |
mov al,0b10101010 or al,0b11110000 |
Result | 0b01011010 | 0b10100000 | 0b11111010 |
Meaning | Invert the bits where the mask bits are 1 |
return 1 where both bits are1 | Return 1 when either bit is 1 |
Sample | XOR al,0b11110000 Invert Bits that are 1 |
AND
al,0b11110000 Keep Bits that are 1 |
OR al,0b11110000 Set Bits that are 1 |
AND
doesn't just alter the register - it also sets the flags
accordingly - so the Z flag will be set if the result is
zero... If you want to set the flags in this way, but leave the register unchanged use TEST - it has the same effect on the flags as AND, but leaves the registers unchaged! |
While SAR and SHR are
different... SHL and SAL do the same thing! it doesn't matter
which you use - so don't worry! |
Wondering
how you're supposed to deal with the other flags? well there's
no commands to directly set or clear them! You'll have to do something else - the best thing to do is push the flags onto the stack, alter them on the stack (or pop them into ax) and then pop them back SAFH probably won't help, as that only affects the bottom half of the flags register |
Lesson
6 - Carry for 32 bit, Multiplication, Division, Ports and
Interrupts We've covered a lot of commands, but there's a few more complex ones we need to go over to do the 8086 justice, Lets go over them now! |
Although our registers are only 16 bit, we can use a pair of
them together to make a 32 bit pair... one register will be the
Low part of the 32 bit pair, the other will be the High part When we do addition or subtraction, the Carry flag can be used as a Carry or Borrow to add or remove from the High register... (the Carry flag functions as a borrow for subtraction) We first do addition or subtraction from the Low Register (BX in this example) using the regular ADD or SUB... then we perform the addition or subtraction with the carry on the high part using ADC (add with Carry) or SBB (Subtract with Borrow) If we don't want to add or subtract anything from the H you would do ADC ax,0 or SBB ax,0 - because you'd still need to apply any carry or borrow to the high register |
|
when the Carry flag is set.. the ADC or SBC adds or subtracts an extra 1 from the top register |
Unlike many 8 bit processors, the 8086 has multiplication
commands... they can work with bytes or words, but the result is
always twice the size... there are two command, IMUL works with
signed numbers, MUL works with unsigned numbers... if you use an 8 bit parameter (eg BL) then the command: IMUL BL will perform AH*BL - returning the result in AX ( MUL BL would be the same) if you use an 16 bit parameter (eg BX) then the command: IMUL BX will perform AX*BX - returning the result in DX.AX - a 32 bit pair where DX is the High word, and AX is the low word (MUL BX would be the same) |
|
The results of each command are shown here. |
When performing Division there are a couple of 'gochas' we have
to be ready for! The first is the classic 'Division by zero' (if it takes 1 person 10 minutes to eat a cake, and 2 people 5 minutes - how long will the cake last if 0 people eat it?)... Division by zero causes Interrupt 0 and will lock the machine. The other is 'Overflow)... if we Divide 1000 by 1, and the result is to be stored in a byte, it won't fit! this is called overflow and causes Interrupt 4 We should range check our parameters first! Just like before IDIV works with signed parameters, and DIV works with unsigned ones IDIV BL will perform AX / BL - returning the integer result in AL and the remainder in AH (DIV BL would be the same) if you use an 16 bit parameter (eg BX) then the command: IDIV BX will perform DX.AX / BX (where DX.AX is a 32 bit pair) - returning the integer result in AX and the remainder in DX (DIV BX would be the same) |
|
The results of each command are shown here. |
'PORTS' are the connections from the main CPU to peripherals -
this is how we transfer data to and from these devices. This example sends data OUT to port 42h (the speaker)... and reads it IN from port 61h (so we can enable the speaker bits,but leave the others alone) We'll look more at the speaker example in a later lesson... Another command we show here is NOP... this command does literally nothing, here we use it as a very crude delay... but it can also be used in self modifying code (code that alters it's own code) |
Interrupts are tasks which override our program and run
immediately... Hardware interrupts are where a device is taking control.. software interrupts occur for different circumstances (Like Division by zero), and we can even cause them ourselves with an INT command... (like a RST on Z80 / SWI on ARM or TRAP on 68000) INTerrupts are used by DOS - and we can use them as OS calls to start DOS functions such as printing a string and returning to the OS |
|
Software interrupts call addresses from 0000:0000+... each uses
2 words - the first is the code segment of the interrupt handler,
the second is the address of the handler... We can program a custom interrupt handler for INT4 (We need to use RETI to end the interrupt handler Another interesting one is INT2 the 'Debugging Step Trap' - if we turn on the Trap flag this interrupt will occur every command - it's intended for trace debugging. |
|
Our INT4 ran twice... and the Step trap shows the changes of AX while the Trap flag was on |
What ports and
interrupt numbers do is a mystery - it all depends on the
machine setup - you'll need to check the documentation of the
machine to understand using the OS Interrupt numbers, and what
the ports do with the attached hardware. |
Lesson
7 - Strings and stuff! We've covered lots of commands now, but we've been overlooking some of the most powerful... remember the weird SI and DI registers that we saw at the start, that don't quite work like the general one? We'll these are for something called 'Strings' - nothing to do with text (although they could be), these commands perform fast sequential operations!... Lets put them to work! |
Command |
Source |
Destination |
Notes |
|
CMPSb/w |
DS:SI | ES:DI | Compare bytes between source and destination (Use REPZ / REPNZ) | |
LODSb/w |
DS:SI | Load a byte from the source | ||
MOVSb/w |
DS:SI | ES:DI | Move Data from Source to Destination in Words or Bytes | |
SCASb/w |
|
Scan Destination for AX (Use REPZ / REPNZ) | ||
STOSb/w |
AX | ES:DI | Set bytes to AX/AL |
String
functions are like the LDI command on the Z80 - they do a job
then stop, so we can do some extra processing Adding REP is like LDIR - and processes the string repeatedly until CX reaches zero |
MOVSB/W will move a sequence of bytes
or words from DS:SI to ES:DI... we can use REP to repeat - this will copy CX bytes or CX words. we can use STD to reverse the direction of the copy If we want to store a sequence of the same byte or word, we can use STOSB/W instead. |
|
We copied 3 bytes from the source to the destination in the first example | |
in the second screenshot I enabled STD, reversing the procedure,, and used REP STOSW to copy AX to a range of 3 words |
CMPSB/W compares two sequences, one at
DS:SI and one at ES:DI We needs to use REPZ or REPNZ to repeat it - and set CX. REPZ will continue until the strings no longer match REPNZ will continue until the strings start to match. |
|
The routine scanned the string until
they stopped matching (and the Zero flag stopped being set)... DI points to the following byte after the routine ends... also note CX did not reach zero |
SCAS will scan a string and compare it
to AX (or AL) We can use REPZ to scan until the bytes don't match AX/AL or REPNZ to scan until the bytes do match AX/AL |
|
We set the Direction flag with STD so we went backwards... scanning words until we found one that didn't match AX - DI then points to the word before |
If we're looking to process bytes or words from a sequence we
can use LODS... like the z80 ldi command, this can be used as a
quick way of reading in from a range and performing commands on
those read in bytes or words. In this example we'll read in bytes with LODSB, then words with LODSW from the string. this command can be used with REP, but I'm not sure what the purpose would be - as SCAS can be used for scanning, and the repeat will not do anything with the read in data. |
|
We loaded in 3 Bytes and then 3 words |
XLAT is a translation command - it uses a lookup table in
[DS:BX] and loads AL with the value at offset AL (AL = [DS:BX+AL]) In this example we use XLAT to convert a number to a pair of nibbles with that number... Not particularly useful, but it will show what the command does. |
|
the XLAT command has converted AL according to the look up table |
Phew!
we've covered all the major 8086 commands! We should be able to make a decent effort at some programming now... Join in on the platform specific series next, In which we'll learn about the DOS and WonderSwan hardware! |
Mnemonic | Description | Example | Valid Regs | Flags affected |
AAA | ASCII Adjust for Addition. Treats AL as an unpacked binary coded decimal number | AAA | o s z A p C | |
AAD | ASCII Adjust for Division. AL=AL+(AH*10), AH=0. | AAD | o S Z a P c | |
AAM | ASCII Adjust for Multiplication. We can use the normal MUL command then use AAM | AAM | o S Z a P c | |
AAS | ASCII Adjust for Subtraction. This treats AL as an unpacked binary coded decimal number | AAS | o s z A p C | |
ADC dest,src | Add src and the carry flag to dest. | ADC CX,1000h | O S Z A P C | |
ADD dest,src | Add src to dest. | ADD CX,1000h | O S Z A P C | |
AND dest,src | Logical AND of bits in dest with Accumulator scr. | AND AX,1100h | O S Z A P C | |
CALL dest | Call Subroutine at address dest. | CALL 1000h | - - - - - - | |
CBW | Convert the 8 bit byte in AL into a 16 bit word in AX. | CBW | - - - - - - | |
CLC | Clear the Carry Flag. C flag will be set to Zero. | CLC | - - - - - C | |
CLD | Clear the Direction Flag. D flag will be set to Zero. This is used for 'String functions'. | CLD | D - - - - - - | |
CLI | Clear the Interrupt enable flag. I flag will be set to 0. This disables maskable interrupts. | CLI | I - - - - - - | |
CMC | Complement the Carry flag. If C=1 it will now be 0. If it was 0 it will now be 1. | CMC | - - - - - C | |
CMP dest,src | Compare the Byte or Word dest to src. This sets the flags the same as "SUB dest,src" would. | CMP AL,32 | O S Z A P C | |
CMPSB CMPSW |
Compare DS:SI to ES:DI. This command can work in bytes or words. Sets flags like CMP | REPZ CMPSB | O S Z A P C | |
CWD | Convert the 16 bit word in AX into a 32 bit doubleword in DX.AX. This 'Sign Extends' AX | CWD | - - - - - - | |
DAA | Decimal Adjust for Addition. This treats AL as a packed binary coded decimal number. | DAA | O S Z A P C | |
DAS | Decimal Adjust for Subtraction. This treats AL as a packed binary coded decimal number. | DAS | O S Z A P C | |
DEC Dest | Divide Unsigned number AX or DX.AX by src. | DEC AL | O S Z A P - | |
DIV src | Divide Unsigned number AX or DX.AX by src. AL=AX/src (8 bit) or AX=DX.AX/src (16 bit) | DIV CX | o s z a p c | |
ESC #,src | This command is for working with multiple processors - it's not something you will need. | ESC 1,AH | - - - - - - | |
HLT | Stop the CPU until an interrupt occurs | HLT | - - - - - - | |
IDIV src | Divide Signed number AX or DX.AX by src. AL=AX / src (8 bit) or AX=DX.AX / src (16 bit) | IDIV CX | o s z a p c | |
IMUL src | Multiply Signed number AX or DX.AX by src. AX=AL*src (8 bit) or DX.AX=AX*src (16 bit) | IMUL CX | O s z a p C | |
IN dest,port | Read in an 8 bit byte or 16 bit word into dest (either AX or AL). Use DX for 16 bit port | IN AX,F0h | - - - - - - | |
INC Dest | Increase Dest by one. This is faster than using ADD with a value of 1. | INC AL | O S Z A P - | |
INT # | Causes software interrupt #. The flags are pushed onto the stack before call | INT 33h | - - - - - - | |
INTO | INTO will cause Interrupt 4 if the Overflow flag (O) is set, otherwise it will have no effect. | INTO | - - - - - - | |
IRET | Restore the flags from the stack and return from an Interrupt. | IRET | O S Z A P C | |
Jcc addr | Jump to 8 bit offset addr if condition cc is true. | JO ErrorHandle | - - - - - - | |
JCXZ addr | Jump to 8 bit offset addr if CX=0. | JCXZ NoLoop | - - - - - - | |
JMP addr | Jump to address addr. | JMP BX | - - - - - - | |
LAHF | Load AH from the Flags. This only transfers the main flags: SZ-A-P-C | LAHF | - - - - - - | |
LDS reg,addr | Load a full 32 bit pointer into DS segment register and register reg. | LDS BX,TestPointer | AX, BX, CX, DX, SI, DI | - - - - - - |
LEA reg,src | Load the effective address src into reg. | LEA CX,[BX+DI] | AX, BX, CX, DX,SI, DI, BP, SP | - - - - - - |
LES reg,addr | Load a full 32 bit pointer into ES segment register and register reg. | LES AX,MyLabel | AX,BX,CX,DX,SI,DI | - - - - - - |
LOCK | Enable the LOCK signal. This is for multiprocessor systems. | LOCK | - - - - - - | |
LODSBLODSW | Load from DS:SI into AX or AL. This command can work in bytes or words. | LODSB | - - - - - - | |
LOOP addr | Decrease CX and jump to label addr if CX is not zero. | LOOP LoopLabel | - - - - - - | |
LOOPNZ addr LOOPNE addr |
Decrease CX and jump to label addr if CX is not zero and the Zero flag is not set. | LOOPNZ LoopLabel | - - - - - - | |
LOOPZ addr LOOPE addr |
Decrease CX and jump to label addr if CX is not zero and the Zero flag is set. | LOOPZ LoopLabel | - - - - - - | |
MOV dest,src | Move a value from source src to destination dest | MOV AX,BX | - - - - - - | |
MOVSB MOVSW |
Move a byte or word from DS:SI to
ES:DI. (Like Z80 LDIR) This command can be combined with repeat command REP, to repeat CX times. |
REPZ MOVSB | - - - - - - | |
MUL src | Multiply unsigned number AX or DX.AX by src.AX=AL*src (8 bit) or DX.AX=AX*src (16 bit) | MUL CX | O s z a p C | |
NEG dest | Negate dest (Twos Complement of the number). | NEG AL | - - - - - - | |
NOP | No Operation. This command has no effect on any registers or memory. | NOP | - - - - - - | |
NOT dest | Invert/Flip all the bits of dest. | NOT dest | - - - - - - | |
OR dest,src | Logically ORs the src and dest parameter together. | OR AX,BX | O S Z a P C | |
OUT port,src | Send an 8 bit byte or 16 bit word from src (either AX or AL) to hardware port number port. Use DX for 16 bit port | OUT 100,AL | - - - - - - | |
POP reg | Pop a pair of bytes off the stack into 16 bit register reg. | POP ES | AX, BX, CX, DX, SI, DI, SP, BP, CS, DS, ES, SS | - - - - - - |
POPF | Pop a pair of bytes off the stack into the 16 bit Flags register. | POPF | O D I T S Z A P C | |
PUSH reg | Push a pair of bytes from 16 bit register reg onto the top of the stack. | PUSH AX | - - - - - - | |
PUSHF | Push a pair of bytes off the stack into the 16 bit Flags register. | PUSHF | - - - - - - | |
RCL dest,count | Rotate bits in Destination dest to the Left by count bits, with the carry flag acting as an extra bit. | RCL AX,1 | O - - - - C | |
RCR dest,count | Rotate bits in Destination dest to the Right by count bits, with the carry flag acting as an extra bit | RCR AX,1 | O - - - - C | |
REP stringop | Repeat string operation stringop while CX>0. Decrease CX after each iteration | REP LODSW | - - - - - - | |
REPE stringop REPZ stringop |
Repeat string operation stringop while the Z flag is set and CX>0. Decrease CX each time | REPZ CMPSB | - - - - - - | |
REPNE stringop REPNZ stringop |
Repeat string operation stringop while the Z flag is not set and CX>0. Decrease CX each time | REPNZ CMPSB | - - - - - - | |
RET | Return from a subroutine. | RET | - - - - - - | |
ROL dest,count | Rotate bits in Destination dest to the Left by count bits | ROL AX,1 | O - - - - C | |
ROR dest,count | Rotate bits in Destination dest to the Right by count bits | ROR AL,1 | O - - - - C | |
SAHF | Store AH to the Flags. This only transfers the main flags: SZ-A-P-C . | SAHF | - S Z A P C | |
SAL dest,count | Shift the bits for Arithmetic in Destination dest to the Left by count bits. | SAL AX,1 | O - - - - C | |
SAR dest,count | Shift the bits for Arithmetic in Destination dest to the Right by count bits. | SAR AX,1 | O - - - - C | |
SBB dest,src | Subtract src and the Borrow (carry flag) from dest. | SBB AL,BL | O S Z A P C | |
SCASB SCASW |
Scan ES:DI and compare to AX or AL. This command can work in bytes or words. (Like CMP) | REPZ SCASB | O S Z A P C | |
SHL dest,count | Shift the bits logically Left in destination dest by count bits. | SHL AX,1 | O - - - - C | |
SHR dest,count | Shift the bits logically Right in destination dest by count bits. | SHR AX,1 | O - - - - C | |
STC | Set the Carry Flag. C flag will be set to 1. | STC | - - - - - C | |
STD | Set the Direction Flag. D flag will be set to 1. This is used for 'String functions'. | STD | D - - - - - - | |
STI | Set the Interrupt enable flag. I flag will be set to 1. This enables maskable interrupts. | STI | I - - - - - - | |
STOSB STOSW |
Store AX or AL to ES:DI. This command can work in bytes or words. | REP STOSB | - - - - - - | |
SUB dest,src | Subtract src from dest. | SUB AX,BX | O S Z A P C | |
TEST dest,src | Test dest, setting the flags in the same way a logical "AND src" would. Dest unchanged | TEST BX,64h | O S Z A P C | |
WAIT | Wait until the busy pin of the CPU is inactive. | WAIT | O S Z A P C | |
XCHG reg1,reg2 | Exchange the contents of registers reg1 and reg2. | XCHG BH,AL | - - - - - | |
XLAT | Translate AL using lookup table DS:BX. AL is read from memory address [DS:BX+AL]. | XLAT | - - - - - - |
View Options |
Default Dark |
Simple (Hide this menu) |
Print Mode (white background) |
Top Menu |
***Main Menu*** |
Youtube channel |
Patreon |
Introduction to Assembly (Basics for absolute beginners) |
Amazon Affiliate Link |
AkuSprite Editor |
ChibiTracker |
Dec/Bin/Hex/Oct/Ascii Table |
Alt Tech |
Archive.org |
Bitchute |
Odysee |
Rumble |
DailyMotion |
Please note: I wlll upload more content to these alt platforms based on the views they bring in |
Z80 Content |
***Z80 Tutorial List*** |
Learn Z80 Assembly (2021) |
Learn Z80 Assembly (old) |
Hello World |
Simple Samples |
Advanced Series |
Multiplatform Series |
Platform Specific Series |
ChibiAkumas Series |
Grime Z80 |
Z80 Downloads |
Z80 Cheatsheet |
Sources.7z |
DevTools kit |
Z80 Platforms |
Amstrad CPC |
Elan Enterprise |
Gameboy & Gameboy Color |
Master System & GameGear |
MSX & MSX2 |
Sam Coupe |
TI-83 |
ZX Spectrum |
Spectrum NEXT |
Camputers Lynx |
6502 Content |
***6502 Tutorial List*** |
Learn 6502 Assembly |
Advanced Series |
Platform Specific Series |
Hello World Series |
Simple Samples |
Grime 6502 |
6502 Downloads |
6502 Cheatsheet |
Sources.7z |
DevTools kit |
6502 Platforms |
Apple IIe |
Atari 800 and 5200 |
Atari Lynx |
BBC Micro |
Commodore 64 |
Commodore PET |
Commander x16 |
Super Nintendo (SNES) |
Nintendo NES / Famicom |
PC Engine (Turbografx-16) |
Vic 20 |
68000 Content |
***68000 Tutorial List*** |
Learn 68000 Assembly |
Hello World Series |
Platform Specific Series |
Simple Samples |
Grime 68000 |
68000 Downloads |
68000 Cheatsheet |
Sources.7z |
DevTools kit |
68000 Platforms |
Amiga 500 |
Atari ST |
Neo Geo |
Sega Genesis / Mega Drive |
Sinclair QL |
X68000 (Sharp x68k) |
8086 Content |
Learn 8086 Assembly |
Platform Specific Series |
Hello World Series |
Simple Samples |
8086 Downloads |
8086 Cheatsheet |
Sources.7z |
DevTools kit |
8086 Platforms |
Wonderswan |
MsDos |
ARM Content |
Learn ARM Assembly |
Learn ARM Thumb Assembly |
Platform Specific Series |
Hello World |
Simple Samples |
ARM Downloads |
ARM Cheatsheet |
Sources.7z |
DevTools kit |
ARM Platforms |
Gameboy Advance |
Nintendo DS |
Risc Os |
Risc-V Content |
Learn Risc-V Assembly |
Risc-V Downloads |
Risc-V Cheatsheet |
Sources.7z |
DevTools kit |
MIPS Content |
Learn Risc-V Assembly |
Platform Specific Series |
Hello World |
Simple Samples |
MIPS Downloads |
MIPS Cheatsheet |
Sources.7z |
DevTools kit |
MIPS Platforms |
Playstation |
N64 |
PDP-11 Content |
Learn PDP-11 Assembly |
Platform Specific Series |
Simple Samples |
PDP-11 Downloads |
PDP-11 Cheatsheet |
Sources.7z |
DevTools kit |
PDP-11 Platforms |
PDP-11 |
UKNC |
TMS9900 Content |
Learn TMS9900 Assembly |
Platform Specific Series |
Hello World |
TMS9900 Downloads |
TMS9900 Cheatsheet |
Sources.7z |
DevTools kit |
TMS9900 Platforms |
Ti 99 |
6809 Content |
Learn 6809 Assembly |
Learn 6309 Assembly |
Platform Specific Series |
Hello World Series |
Simple Samples |
6809 Downloads |
6809/6309 Cheatsheet |
Sources.7z |
DevTools kit |
6809 Platforms |
Dragon 32/Tandy Coco |
Fujitsu FM7 |
TRS-80 Coco 3 |
Vectrex |
65816 Content |
Learn 65816 Assembly |
Hello World |
Simple Samples |
65816 Downloads |
65816 Cheatsheet |
Sources.7z |
DevTools kit |
65816 Platforms |
SNES |
eZ80 Content |
Learn eZ80 Assembly |
Platform Specific Series |
eZ80 Downloads |
eZ80 Cheatsheet |
Sources.7z |
DevTools kit |
eZ80 Platforms |
Ti84 PCE |
IBM370 Content |
Learn IBM370 Assembly |
Simple Samples |
IBM370 Downloads |
IBM370 Cheatsheet |
Sources.7z |
DevTools kit |
Super-H Content |
Learn SH2 Assembly |
Hello World Series |
Simple Samples |
SH2 Downloads |
SH2 Cheatsheet |
Sources.7z |
DevTools kit |
SH2 Platforms |
32x |
Saturn |
PowerPC Content |
Learn PowerPC Assembly |
Hello World Series |
Simple Samples |
PowerPC Downloads |
PowerPC Cheatsheet |
Sources.7z |
DevTools kit |
PowerPC Platforms |
Gamecube |
Work in Progress |
ChibiAndroids |
Misc bits |
Ruby programming |