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:
DIV
operates on a 32 bit integer composed ofY:A
. So multipleDIV
instructions 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