Table of Contents

Introduction

This simulator provides a simplified assembler syntax (based on NASM) and is simulating a x86 like CPU. In depth documentation and introduction to assembler can be found on the following websites:

The simulator consists of a 16-bit CPU and 1024 bytes of memory (0x0 to 0x3FF). All instructions (code) and variables (data) needs to fit inside the memory. For simplicity every instruction is 1, 3 or 5 byte and every operand is 2 bytes. Therefore a MOV instruction will use 5 bytes of memory. The simulator provides a console output which is memory mapped from 0x1E0 to 0x1FF. Memory mapped means that every value written to this memory block is visible on the console.

The simulator features a supervisor mode. For this purpose a supervisor flag (S) exists. Addresses in the upper half of the memory (0x0 to 0x0x1FF) can only be accessed if the CPU runs in supervisor mode (supervisor flag must be set), otherwise the CPU switches to a fault state (fault flag will be set). The only way to switch from user mode to supervisor mode is to call an interrupt service routine.

Interrupt service routines (ISRs) must be defined in the upper half of the memory (in the kernel space) and can be called within the user or kernel space via the INT instruction. To register an ISR, the start address of the ISR must be copied to the interrupt vector table:

Number Address
0 0x0
1 0x2
2 0x4
3 0x6
4 0x8
5 0xA
6 0xC
7 0xE

Syntax

The syntax is similar as most assemblers are using. Every instruction must be on their own line. Labels are optional and must either start with a letter or a dot (.) and end with a colon (:).

label: instruction operands	; Comment

Valid number formats for constants are:

Decimal: 200
Decimal: 200d
Hex: 0xA4
Octal: 0o48
Binary: 101b

It is possible to define a number using a character or multiple numbers (see instruction DB) by using a string.

Character: 'A'
String: "Hello World!"

Operands can either be one of the four general purpose registers, stack pointer register, a memory address or a constant. Stack pointer register (SP) can only be used as operand in MOV, ADD, SUB, CMP, INC and DEC instructions. Instead of defining an address as a constant or by using a register you can use labels. The assembler will then replace the label with the corresponding constant.

General purpose (GP) register: A, B, C, D
Stack pointer register: SP
Address using a GP register: [A]
Address using a GP register and offset: [D-3]
Address using SP register and offset: [SP+2]
Address using a constant: [100]
Address using a label: label
Constant: Any number between 0..255 (8-bit unsigned)
Offset for indirect addressing: Integer between -4096..+4095 (sign is mandatory)

MOV – Copy a value

Copies a value from src to dest. The MOV instruction is the only one able to directly modify the memory. SP can be used as operand with MOV.

MOV [BYTE] reg, reg
MOV [BYTE] reg, address
MOV [BYTE] reg, constant
MOV [BYTE] address, reg
MOV [BYTE] address, constant

DB – Variable

Defines a variable. A variable can either be a single number, character or a string.

DB constant

Math operations

Addition and Subtraction

Adds two numbers together or subtract one number form another. This operations will modify the carry and zero flag. SP can be used as operand with ADD and SUB.

ADD [BYTE] reg, reg
ADD [BYTE] reg, address
ADD [BYTE] reg, constant

SUB [BYTE] reg, reg
SUB [BYTE] reg, address
SUB [BYTE] reg, constant

Increment and Decrement

Increments or decrements a register by one. This operations will modify the carry and zero flag. SP can be used as operand with INC and DEC.

INC [BYTE] reg
DEC [BYTE] reg

Multiplication and division

Multiplies or divides the A register with the given value. This operations will modify the carry and zero flag.

MUL [BYTE] reg
MUL [BYTE] address
MUL [BYTE] constant

DIV [BYTE] reg
DIV [BYTE] address
DIV [BYTE] constant

Logical instructions

The following logical instructions are supported: AND, OR, XOR, NOT. This operations will modify the carry and zero flag.

AND [BYTE] reg, reg
AND [BYTE] reg, address
AND [BYTE] reg, constant

OR [BYTE] reg, reg
OR [BYTE] reg, address
OR [BYTE] reg, constant

XOR [BYTE] reg, reg
XOR [BYTE] reg, address
XOR [BYTE] reg, constant

NOT [BYTE] reg

Shift instructions

The following shift instructions are supported: SHL/SAL and SHR/SAR. As this simulator only supports unsigned numbers SHR and SAR yield the same result. This operations will modify the carry and zero flag.

SHL [BYTE] reg, reg
SHL [BYTE] reg, address
SHL [BYTE] reg, constant

SHR [BYTE] reg, reg
SHR [BYTE] reg, address
SHR [BYTE] reg, constant

CMP – Compare

Compares two values and sets the zero flag to true if they are equal. SP can be used as operand with CMP. Use this instruction before a conditional jump.

CMP [BYTE] reg, reg
CMP [BYTE] reg, address
CMP [BYTE] reg, constant

Jumps

JMP – Unconditional jump

Let the instruction pointer do a unconditional jump to the defined address.

JMP address

Conditional jumps

Let the instruction pointer do a conditional jump to the defined address. See the table below for the available conditions.

Instruction Description Condition Alternatives
JC Jump if carry Carry = TRUE JB, JNAE
JNC Jump if no carry Carry = FALSE JNB, JAE
JZ Jump if zero Zero = TRUE JB, JE
JNZ Jump if no zero Zero = FALSE JNE
JA > Carry = FALSE && Zero = FALSE JNBE
JNBE not <= Carry = FALSE && Zero = FALSE JA
JAE >= Carry = FALSE JNC, JNB
JNB not < Carry = FALSE JNC, JAE
JB < Carry = TRUE JC, JNAE
JNAE not >= Carry = TRUE JC, JB
JBE <= C = TRUE or Z = TRUE JNA
JNA not > C = TRUE or Z = TRUE JBE
JE = Z = TRUE JZ
JNE != Z = FALSE JNZ

CALL – Function call

Call can be used to jump into a subroutine (function). Pushes the instruction address of the next instruction to the stack and jumps to the specified address.

CALL address

RET – Exit a subroutine

Exits a subroutines by popping the return address previously pushed by the CALL instruction. Make sure the SP is balanced before calling RET otherwise the instruction pointer will have an ambiguous value.

RET

Stack instructions

PUSH – Push to stack

Pushes a value to the stack. The stack grows down and the current position is available in the SP. This instruction will decrease the SP.

PUSH reg
PUSH address
PUSH constant

POP – Pop from stack

Pops a value from the stack to a register. This instruction will increase the SP.

POP reg

Interrupt instructions

INT – Call interrupt service routine

Calls an interrupt service routine with the given number. The IP will be saved on the stack.

INT constant

IRET – Exit interrupt service routine

Exists an interrupt service routine by jumping to the IP restored from the stack.

IRET

Other instructions

HLT – Stops the processor

Stops operation of the processor. Hit Reset button to reset IP before restarting.

HLT