Table of Contents
- Instruction set
- Instruction Set
Instruction set
The instruction table and instructions are sorted alphabetically.
Opcodes in use
Current opcodes in use
0
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, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49 50
63
Current opcodes unsused
51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62
Instruction table with affected flags
| Instruction mnemonic | Operands | Opcode | C Z S O B |
|---|---|---|---|
| ADD destination, source | mem/reg, mem/reg/imm | 0x02 | X X X X - |
| AND destination, source | mem/reg, mem/reg/imm | 0x04 | 0 X X 0 - |
| BRK | None | 0x00 | - - - - 1 |
| CALL target | mem/reg/imm | 0x15 | - - - - - |
| CMP destination, source | mem/reg, mem/reg/imm | 0x0C | X X X X - |
| DEC destination | mem/reg | 0x2B | - X X X - |
| DIV source | mem/reg/imm | 0x18 | - - - - - |
| HWI source | mem/reg/imm | 0x09 | - - - - - |
| HWQ source | mem/reg/imm | 0x1C | - - - - - |
| INC destination | mem/reg | 0x2A | - X X X - |
| INT | imm (0-255) | 0x30 | - - - - - |
| INTO | None | 0x08 | - - - - - |
| IRET | None | 0x31 | - - - - - |
| JA target | mem/reg/imm | 0x2E | - - - - - |
| JAE target | mem/reg/imm | 0x22 | - - - - - |
| JC target | mem/reg/imm | 0x21 | - - - - - |
| JG target | mem/reg/imm | 0x0F | - - - - - |
| JGE target | mem/reg/imm | 0x10 | - - - - - |
| JL target | mem/reg/imm | 0x11 | - - - - - |
| JLE target | mem/reg/imm | 0x12 | - - - - - |
| JMP target | mem/reg/imm | 0x0A | - - - - - |
| JNA target | mem/reg/imm | 0x2F | - - - - - |
| JNC target | mem/reg/imm | 0x22 | - - - - - |
| JNO target | mem/reg/imm | 0x25 | - - - - - |
| JNS target | mem/reg/imm | 0x1B | - - - - - |
| JNZ target | mem/reg/imm | 0x0D | - - - - - |
| JO target | mem/reg/imm | 0x24 | - - - - - |
| JS target | mem/reg/imm | 0x1A | - - - - - |
| JZ target | mem/reg/imm | 0x0E | - - - - - |
| MOV destination, source | mem/reg, mem/reg/imm | 0x01 | - - - - - |
| MUL source | mem/reg/imm | 0x17 | X - - X - |
| NEG destination | mem/reg | 0x19 | X X X X -* |
| NOP | None | 0x3F | - - - - - |
| NOT destination | mem/reg | 0x1D | - - - - - |
| OR destination, source | mem/reg, mem/reg/imm | 0x05 | 0 X X 0 - |
| POP destination | mem/reg | 0x14 | - - - - - |
| POPF | None | 0x2C | X X X X - |
| PUSH source | mem/reg/imm | 0x13 | - - - - - |
| PUSHF | None | 0x2D | - - - - - |
| RCL destination, count | mem/reg, mem/reg/imm | 0x27 | X - - X - |
| RCR destination, count | mem/reg, mem/reg/imm | 0x28 | X - - X - |
| RET optional-pop-value | imm/None | 0x16 | - - - - - |
| ROL destination, count | mem/reg, mem/reg/imm | 0x23 | X - - X - |
| ROR destination, count | mem/reg, mem/reg/imm | 0x20 | X - - X - |
| SAL destination, count | mem/reg, mem/reg/imm | 0x06 | X - - X - |
| SAR destination, count | mem/reg, mem/reg/imm | 0x29 | X - - X - |
| SETcc destination | mem/reg | 0x32 | - - - - - |
| SETA destination | mem/reg | 0x32 | - - - - - |
| SETAE destination | mem/reg | 0x32 | - - - - - |
| SETB destination | mem/reg | 0x32 | - - - - - |
| SETBE destination | mem/reg | 0x32 | - - - - - |
| SETC destination | mem/reg | 0x32 | - - - - - |
| SETE destination | mem/reg | 0x32 | - - - - - |
| SETG destination | mem/reg | 0x32 | - - - - - |
| SETGE destination | mem/reg | 0x32 | - - - - - |
| SETL destination | mem/reg | 0x32 | - - - - - |
| SETLE destination | mem/reg | 0x32 | - - - - - |
| SETS destination | mem/reg | 0x32 | - - - - - |
| SETO destination | mem/reg | 0x32 | - - - - - |
| SETZ destination | mem/reg | 0x32 | - - - - - |
| SETNA destination | mem/reg | 0x32 | - - - - - |
| SETNAE destination | mem/reg | 0x32 | - - - - - |
| SETNB destination | mem/reg | 0x32 | - - - - - |
| SETNBE destination | mem/reg | 0x32 | - - - - - |
| SETNC destination | mem/reg | 0x32 | - - - - - |
| SETNE destination | mem/reg | 0x32 | - - - - - |
| SETNG destination | mem/reg | 0x32 | - - - - - |
| SETNGE destination | mem/reg | 0x32 | - - - - - |
| SETNL destination | mem/reg | 0x32 | - - - - - |
| SETNLE destination | mem/reg | 0x32 | - - - - - |
| SETNO destination | mem/reg | 0x32 | - - - - - |
| SETNS destination | mem/reg | 0x32 | - - - - - |
| SETNZ destination | mem/reg | 0x32 | - - - - - |
| SHL destination, count | mem/reg, mem/reg/imm | 0x06 | X - - X - |
| SHR destination, count | mem/reg, mem/reg/imm | 0x07 | X - - X - |
| SUB destination, source | mem/reg, mem/reg/imm | 0x03 | X X X X - |
| TEST destination, source | mem/reg, mem/reg/imm | 0x0B | 0 X X 0 - |
| XCHG destination, source | mem/reg, mem/reg | 0x1F | - - - - - |
| XOR destination, source | mem/reg, mem/reg/imm | 0x26 | 0 X X 0 - |
Instruction Set
Introduction
This is an effort to specify the specific MAR Assembly Instruction Set and its behavior. The instruction set is a subset of the 8086 instruction set. A more detailed specification of the 8086 Instruction Set can be found here. Note that the MAR Instruction Set can differ from the 8086 Instruction Set.
This manual tries to describe how to use the instructions and show any side effects they might have.
Each instruction has a Mnemonic or syntax. This is the way the instruction is written in human readable format. This exists of the instruction name and its operands (if any).
MOV A, 0x20
This human readable format is parsed by the assembler which will output the actual binary opcodes and operands.
Instruction encoding
Instructions are 1-3 words long and are fully defined by the first word.
In a basic instruction, the lower 6 bits of the first word of the instruction
are the opcode, and the remaining 10 bits are split into a 5 bit destination operand
and a 5 bit source operand.
In bits, a basic instruction has the format: sssssdddddoooooo
Operand value:
| Description | Value |
|---|---|
| Invalid or none | 00000 |
| Immediate value at IP+1 | 11111 |
| [Immediate value at IP+1] | 11110 |
| Register | 00001-01000 |
| [Register] | 01001-10000 |
| Register + Immediate value at IP+1 | 10001-11000 |
Flags
Some instructions will change certain flags based on their result. These are in a special non read-write register. These flags are used for the family of jump instructions. You can also use the PUSHF and POPF instructions to query and manipulate the flags
for more information check the docs NOTE: The table below was copied from the link above. There is more info available, if you have trouble understanding the flags we strongly suggest you read the section in the link.
| Flag | Description |
|---|---|
| CF (Carry flag) | Relevant for unsigned operations. Indicates that there was a carry out of the most significant (leftmost) bit |
| ZF (Zero flag) | Indicates that the result of an operation is 0 |
| SF (Sign flag) | Indicates that the most significant (leftmost) bit of the result of an operation is set |
| OF (Overflow flag) | Relevant for signed operations. Indicates that the sign of the result of an signed operation is wrong (See examples below) |
| BF (Break flag) | Tells the CPU to stop the execution. This flag is set with the BRK instruction. |
Instructions
ADD
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
ADD destination, source |
0x02 |
destination : reg / mem |
X |
X |
X |
X |
- |
source : reg / mem / imm |
Description
ADD replaces the destination operand with the sum of the source and destination operands. It sets the carry flag if there is an overflow.
Pseudo code
destination = destination + source
AND
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
AND destination, source |
0x04 |
destination : reg / mem |
0 |
X |
X |
0 |
- |
source : reg / mem / imm |
Description
AND performs a bit-by-bit logical AND operation on its operands
and stores the result in destination. AND sets each bit of the
result to one if both of the corresponding bits of the operands
are one.
Pseudo code
destination = destination & source
BRK
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
BRK |
0x00 |
- |
- |
- |
- |
1 |
Description
BRK sets the break flag. This will halt execution until the next game 'tick', where it will be cleared and execution resumes from the start of the .text label.
CALL
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
CALL target |
0x15 |
target : reg / mem / imm |
- |
- |
- |
- |
- |
Description
CALL pushes the current instruction pointer on to the stack and then performs a jump to the target address
Pseudo code
SP = SP - 1
memory[SP] = IP
IP = target
CMP
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
CMP destination, source |
0x0C |
destination : reg / mem |
X |
X |
X |
X |
- |
source : reg / mem / imm |
Description
CMP compares two numbers by subtracting the source from the
destination and updates the flags. None of the operands are
changed.
Pseudo code
destination - source # flags will be set
DEC
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
DEC destination |
0x2B |
destination : mem / reg |
- |
X |
X |
X |
- |
Description
DEC subtracts one from the value of destination, replacing the previous value. Unlike SUB the carry flag is not modified. If you wish the carry flag to be modified then use sub dest, 1 instead
Pseudo code
destination = destination - 1
DIV
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
DIV source |
0x18 |
source : mem / reg / imm |
- |
- |
- |
- |
X |
Description
DIV performs unsigned division on Y:A with source as divisor and stores the result into A and the remainder in Y.
Division by zero triggers a INT 0
NOTE:
DIVoperates on a 32 bit integer composed ofY:A. So multipleDIVinstructions without setting Y to what you want will result into unexpected results
This is a somewhat complicated instruction, see the source if needed
Pseudo code
if source == 0:
ERROR_FLAG = 1
BREAK_FLAG = 1
# temp is a 32-bit integer
temp = (Y << 16) | A
A = temp / source # result is floored
Y = temp % source
HWI
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
HWI source |
0x09 |
source : reg / mem / imm |
- |
- |
- |
- |
- |
Description
HWI triggers a Hardware Interrupt. source should be the address of the hardware device. This is different from the RAM memory addresses. See the documentation of the hardware devices to see what an HWI does for each device.
HWQ
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
HWQ source |
0x1C |
source : mem / reg / imm |
- |
- |
- |
- |
- |
Description
HWQ queries the hardware id of the hardware at the hardware address specified by source
Pseudo code
if hardware_memory[source] != None:
B = get_hardware_id(
hardware_memory[source]
)
else:
B = 0
INC
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
INC destination |
0x2A |
destination : mem / reg |
- |
X |
X |
X |
- |
Description
INC adds one to the value of destination, replacing the previous value. Unlike ADD the carry flag is not modified. If you wish the carry flag to be modified then use add dest, 1 instead
Pseudo code
destination = destination + 1
JA
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JA target |
0x2E |
target : mem / reg / imm |
- |
- |
- |
- |
- |
Description
JA jumps to the target if the carry flag and the zero flag are NOT set.
Pseudo code
if CARRY_FLAG == 0 and ZERO_FLAG == 0:
IP = target
JAE
Description
JAE is an alias for the JNC instruction
JC
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JC target |
0x21 |
target : mem / reg / imm |
- |
- |
- |
- |
- |
Description
JC jumps to the target if the carry flag IS set.
Pseudo code
if CARRY_FLAG == 1:
IP = target
JG
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JG target |
0x0F |
target : reg / mem / imm |
- |
- |
- |
- |
- |
Description
JG performs a jump if the sign flag IS EQUAL to the overflow flag AND the zero flag IS NOT set.
Pseudo code
if SIGN_FLAG == OVERFLOW_FLAG and ZERO_FLAG == 0:
IP = target
JGE
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JGE target |
0x10 |
target : reg / mem / imm |
- |
- |
- |
- |
- |
Description
JGE performs a jump if the sign flag IS EQUAL to the overflow flag
Pseudo code
if SIGN_FLAG == OVERFLOW_FLAG:
IP = target
JL
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JL target |
0x11 |
target : reg / mem / imm |
- |
- |
- |
- |
- |
Description
JL performs a jump if the sign flag IS NOT EQUAL to the overflow flag
Pseudo code
if SIGN_FLAG != OVERFLOW_FLAG:
IP = target
JLE
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JLE target |
0x12 |
target : reg / mem / imm |
- |
- |
- |
- |
- |
Description
JLE performs a jump if the sign flag IS NOT EQUAL to the overflow flag OR the zero flag IS set
Pseudo code
if SIGN_FLAG != OVERFLOW_FLAG or ZERO_FLAG == 1:
IP = target
JMP
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JMP target |
0x0A |
target : reg / mem / imm |
- |
- |
- |
- |
- |
Description
JMP performs an unconditional jump to the target memory address and will resume execution there.
Pseudo code
IP = target
JNA
Details
Description
Pseudo code
JNC
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JNC target |
0x22 |
target : mem / reg / imm |
- |
- |
- |
- |
- |
Description
JNC jumps to the target if the carry flag IS NOT set.
Pseudo code
if CARRY_FLAG == 0:
IP = target
JNO
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JNO target |
0x25 |
target : mem / reg / imm |
- |
- |
- |
- |
- |
Description
JNO jumps to the target if the overflow flag IS NOT set.
Pseudo code
if OVERFLOW_FLAG == 0:
IP = target
JNS
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JNS target |
0x1B |
target : mem / reg / imm |
- |
- |
- |
- |
- |
Description
JNS jumps to the target if the sign flag IS NOT set.
Pseudo code
if SIGN_FLAG == 0:
IP = target
JNZ
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JNZ target |
0x0D |
target : reg / mem / imm |
- |
- |
- |
- |
- |
Description
JNZ performs a jump if the zero flag IS NOT set.
Pseudo code
if ZERO_FLAG == 0:
IP = target
JO
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JO target |
0x24 |
target : mem / reg / imm |
- |
- |
- |
- |
- |
Description
JO jumps to the target if the overflow flag IS set.
Pseudo code
if OVERFLOW_FLAG == 1:
IP = target
JS
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JS target |
0x1A |
target : mem / reg / imm |
- |
- |
- |
- |
- |
Description
JS jumps to the target if the sign flag IS set.
Pseudo code
if SIGN_FLAG == 1:
IP = target
JZ
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
JZ target |
0x0E |
target : reg / mem / imm |
- |
- |
- |
- |
- |
Description
JZ performs a jump if the the zero flag IS set.
Pseudo code
if ZERO_FLAG == 1:
IP = target
MOV
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
MOV destination, source |
0x01 |
destination : reg / mem |
- |
- |
- |
- |
- |
source : reg / mem / imm |
Description
MOV transfers (copies) a word from the source operand to the destination operand.
Pseudo code
destination = source
MUL
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
MUL source |
0x17 |
source : mem / reg / imm |
X |
- |
- |
X |
- |
Description
MUL performs unsigned multiplication with A and source and stores the result into Y:A.
The result of the multiplication is stored into Y:A where the higher order bits are stored in Y and the lower order bits are stored in A
The carry and overflow flags are set to 1 if the high-order of the result is bigger than 0; otherwise, CF and OF are reset to 0.
This is a somewhat complicated instruction, see the source if needed
Pseudo code
# result is a 32-bit integer
result = A * source
# get the 16 most significant bits of result
higher_order_word = (result & 0xff00)
if higher_order_word != 0:
OVERFLOW_FLAG = 1
CARRY_FLAG = 1
Y = higher_order_word
else:
OVERFLOW_FLAG = 0
CARRY_FLAG = 0
A = (result & 0x00ff)
# result is stored in Y:A
# you can check if you need Y by check the flags
NEG
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
NEG destination |
0x19 |
destination : mem / reg |
X |
X |
X |
X |
- |
Description
NEG subtracts the destination operand from 0 and returns the result in the destination. This effectively produces the two's complement of the operand.
If the operand is zero, the carry flag is cleared; in all other cases, the carry flag is set.
Attempting to negate a word containing -32,768 causes no change to the operand and sets the Overflow Flag.
Pseudo code
if destination == 0:
CARRY_FLAG = 0
ZERO_FLAG = 1
else:
CARRY_FLAG = 1
if destination == -32768:
OVERFLOW_FLAG = 1
else
destination = 0 - destination # or destination = destination + (-dest)
NOP
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
NOP |
0x3F |
- |
- |
- |
- |
- |
Description
NOP is an instruction that performs no operation. Often used for timing purposes, as a placeholder or for aligning purposes.
Pseudo code
# do nothing
NOT
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
NOT destination |
0x1D |
source : mem / reg |
- |
- |
- |
- |
- |
Description
NOT inverts each bit in its operand, i.e. forms the one's complement.
Pseudo code
dest = ~dest
OR
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
OR destination, source |
0x05 |
destination : reg / mem |
0 |
X |
X |
0 |
- |
source : reg / mem / imm |
Description
OR performs a bit-by-bit logical inclusive OR operation on its
operands and returns the result to destination. OR sets each bit
of the result to one if either or both of the corresponding bits
of the operands are one.
Pseudo code
destination = destination | source
POP
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
POP destination |
0x14 |
destination : reg / mem |
- |
- |
- |
- |
- |
Description
POP copies the value of the memory address specified in the stack pointer to the destination and increments the stack pointer.
The stack grows downwards from 0xFFFF -> 0x0000 So incrementing will 'shrink' the stack
Pseudo code
destination = memory[SP]
SP = SP + 1
POPF
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
POPF |
0x2C |
X |
X |
X |
X |
- |
Description
Pops a word of the top of the stack and uses the 4 lowest bits of the result to set the CPU flags. In the order sign, zero, carry and overflow also represented by the following bit pattern xxxx xxxx xxxx SZCO.
All flags will be according to the corresponding bit values of given word. To only set on flag a PUSHF to query the flags and a bitmask with the desired flag to manipulate should be used.
Pseudo code
flags = memory[SP]
SIGN_FLAG = flags & (1 << 3)
ZERO_FLAG = flags & (1 << 2)
CARRY_FLAG = flags & (1 << 1)
OVERFLOW_FLAG = flags & 1
SP = SP + 1
PUSH
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
PUSH source |
0x13 |
source : reg / mem / imm |
- |
- |
- |
- |
- |
Description
PUSH decrements the stack pointer by one and then copies source to the address the stack pointer is pointing to.
The stack grows downwards from 0xFFFF -> 0x0000 So decrementing will 'grow' the stack
Pseudo code
SP = SP - 1
memory[SP] = source
PUSHF
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
PUSHF |
0x2D |
- |
- |
- |
- |
- |
Description
Pushes the current flags on top of the stack. The flags are present in the 4 lowest bits of the result on the stack. In the order sign, zero, carry and overflow also represented by the following bit pattern xxxx xxxx xxxx SZCO.
To get the state of a single flag you can use a bit mask.
example: the operation flags & 0100 will give a result of 1 if the zero flag was set and a result of 0 if it was unset
Pseudo code
# 0000 0000 0000 SZCO
flags = (SIGN_FLAG << 3) | (ZERO_FLAG << 2) | (CARRY_FLAG << 1) | (OVERFLOW_FLAG)
SP = SP - 1
memory[SP] = flags
RCL
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
RCL destination, count |
0x27 |
destination : mem / reg |
X |
- |
- |
X |
- |
count : mem / reg, imm |
Description
RCL shifts the bits of the destination operand to the left by the
number of bit positions specified in the count operand. A bit
shifted out of the left (high-order) end of the destination enters
the carry flag (CF), and the displaced carry flag rotates around
to enter the vacated right-most bit position of the destination.
Another way of looking at this is to consider the carry flag as
the highest order bit of the word being rotated.
if count is bigger than 16 it will be the remainder of a division by 17.
The shift is repeated the number of times indicated by the count operand
if count equals 1 then the overflow flag will be set if the sign bit of destination has changed
Pseudo code
count = count % 17
# TODO: less implementation more pseudo code
if (destination & 0x8000) > 0:
old_sign_bit = 1
else
old_sign_bit = 0
destination = # ... RCL magic
# carry flag might be set
if (destination & 0x8000) > 0:
new_sign_bit = 1
else:
new_sign_bit = 0
if count == 1:
OVERFLOW_FLAG = (old_sign_bit != new_sign_bit)
RCR
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
RCR destination, count |
0x28 |
destination : mem / reg |
X |
- |
- |
X |
- |
count : mem / reg / imm |
Description
RCR shifts the bits of the destination operand to the right by the
number of bit positions specified in the count operand. A bit
shifted out of the right (low-order) end of the destination enters
the carry flag (CF), and the displaced carry flag rotates around
to enter the vacated left-most bit position of the destination.
Another way of looking at this is to consider the carry flag as
the lowest order bit of the word being rotated.
if count is bigger than 16 it will be the remainder of a division by 17.
The shift is repeated the number of times indicated by the count operand
if count equals 1 then the overflow flag will be set if the sign bit of destination has changed
Pseudo code
count = count % 17
# TODO: less implementation more pseudo code
if (destination & 0x8000) > 0:
old_sign_bit = 1
else
old_sign_bit = 0
destination = # ... RCR magic
# carry flag might be set
if (destination & 0x8000) > 0:
new_sign_bit = 1
else:
new_sign_bit = 0
if count == 1:
OVERFLOW_FLAG = (old_sign_bit != new_sign_bit)
RET
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
RET [amount] |
0x16 |
amount : imm / None |
- |
- |
- |
- |
- |
Description
RET jumps to the address stored at the stack pointer and then increments (pops) that address of the stack.
When amount is given increment the stack pointer the number of times given in amount.
Pseudo code
IP = memory[SP]
if amount == None:
amount = 0
SP = SP + 1 + amount
ROL
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
ROL destination, count |
0x23 |
destination : mem / reg |
X |
- |
- |
X |
- |
count : mem / reg, imm |
Description
ROL shifts the bits of destination operand to the left by the number of bit positions specified by count.
if count is greater than 15 it will be the remainder of a division by 16.
as bits are transferred out the left (high-order) end of the destination, they re-enter on the right (low-order) end. The carry flag (CF) is updated to match the last bit shifted out of the left end.
if count equals 1 then the overflow flag will be set if the sign bit of destination has changed
Pseudo code
count = count % 16
# TODO: less implementation more pseudo code
if (destination & 0x8000) > 0: # check if sign bit was set
old_sign_bit = 1
else
old_sign_bit = 0
destination = #... ROL magic
# carry flag might be set
if (destination & 0x8000) > 0: # check if sign bit was set
new_sign_bit = 1
else
new_sign_bit = 0
if count == 1:
OVERFLOW_FLAG = (old_signbit != new_signbit) # check if sign bit changed
# TODO: less implementation more pseudo code
if (destination & 0x01) == 1:
CARRY_FLAG = 1
else:
CARRY_FLAG = 0
ROR
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
ROR destination, count |
0x20 |
destination : mem / reg |
X |
- |
- |
X |
- |
count : mem / reg, imm |
Description
ROR shifts the bits of destination operand to the right by the number of bit positions specified by count.
if count is greater than 15 it will be the remainder of a division by 16.
as bits are transferred out the right (low-order) end of the destination, they re-enter on the left (high-order) end. The carry flag (CF) is updated to match the last bit shifted out of the right end.
if count equals 1 then the overflow flag will be set if the sign bit of destination has changed
Pseudo code
count = count % 16
# TODO: less implementation more pseudo code
if (destination & 0x8000) > 0: # check if sign bit was set
old_sign_bit = 1
else
old_sign_bit = 0
destination = #... ROR magic
if (destination & 0x8000) > 0: # check if sign bit was set
new_sign_bit = 1
else
new_sign_bit = 0
if count == 1:
OVERFLOW_FLAG = (old_signbit != new_signbit) # check if sign bit changed
if new_sign_bit == 1:
CARRY_FLAG = 1
else:
CARRY_FLAG = 0
SAL
SAL is an alias for the SHL instruction
SAR
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
SAR destination, count |
0x29 |
destination : mem / reg |
X |
X |
X |
X |
- |
count : mem / reg/ imm |
Description
The SAR (Shift Arithmetic Right) instruction shifts the bits of the destination operand downward (toward the least significant bit) by the number of bit positions specified in the second operand (count).
As bits are transferred out of the right (low-order) end of the destination, bits equal to the original sign bit are shifted into the left (high-order) end, thereby preserving the sign bit. The carry flag (CF) is set equal to the last bit shifted out of the right end.
If the count operand is not an immediate 1, the overflow flag (OF) is undefined; otherwise SAR resets OF to zero.
TODO: Not sure if this part is implemented, should check source code
TODO: Plain english? (now copy pasta from the manual)
Pseudo code
destination = destination <<< count
#NOTE: be aware of the difference between a logical and an arithmetic shift
SHL
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
SHL destination, count |
0x06 |
destination : reg / mem |
X |
X |
X |
X |
- |
count : reg / mem / imm |
Description
SHL (Shift Logical Left) shifts the bits of the destination operand upward (toward the
most significant bit) by the number of bit positions specified in
the second operand (count). As bits are transferred out of the
left (high-order) end of the destination, zero bits are shifted
into the right (low-order) end.
The carry flag (CF) is set equal to the last bit shifted out of the left end.
Pseudo code
destination = destination << count
#NOTE: be aware of the difference between a logical and an arithmetic shift
SHR
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
SHR destination, count |
0x07 |
destination : reg / mem |
X |
- |
- |
X |
- |
count : reg / mem / imm |
Description
SHR (Shift Logical Right) shifts the bits of the destination operand downward (toward
the least significant bit) by the number of bit positions
specified in the second operand (count). As bits are transferred
out of the right (low-order) end of the destination, zero bits are
shifted into the left (high-order) end.
Pseudo code
destination = destination >> count
#NOTE: be aware of the difference between a logical and an arithmetic shift
SUB
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
SUB destination, source |
0x03 |
destination : reg / mem |
X |
X |
X |
X |
- |
source : reg / mem / imm |
Description
SUB subtracts the source operand from the destination operand and stores the result in destination.
Pseudo code
destination = destination - source
TEST
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
TEST destination, source |
0x0B |
destination : reg / mem |
0 |
X |
X |
0 |
- |
source : reg / mem / imm |
Description
TEST performs a bitwise AND operation on its two operands and
updates the flags. None of the operands are changed.
Pseudo code
destination & source # flags will be set
XCHG
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
XCHG destination, source |
0x1F |
destination : mem / reg |
- |
- |
- |
- |
- |
source : mem / reg |
Description
XCHG switches the contents of two operands.
Pseudo code
temp = destination
destination = source
source = temp
XOR
Details
| mnemonic | opcode | operands | carry | zero | sign | overflow | break |
|---|---|---|---|---|---|---|---|
XOR destination, source |
0x26 |
destination : reg / mem |
0 |
X |
X |
0 |
- |
source : reg / mem / imm |
Description
XOR performs a bit-by-bit "exclusive or" on its two operands, and returns the result in the destination operand. XOR sets each bit of the result to one if only one of the corresponding bits is set to one.
Pseudo code
destination = destination ^ source