Skip to content

Assembly

Gil Keidar edited this page Sep 7, 2022 · 11 revisions

ByteFrost Assembly language offers some abstraction above the ByteFrost instruction set. Note that there are some differences between the two, as well as overloaded instruction names.

Register File

Assembly Instruction Use Syntax Instruction it's based on Differences from instruction set Affects Flags
LDR Loads register with immediate value LDR Rd, #Imm LDR, opcode 3 No difference No
MOV Copy value of one register and store in another MOV Rd, Rs MOV, opcode 4 No difference No

ALU

ALU instructions have two variants based on opcodes 2 and 6 of the instruction set. This is reflected in assembly as overloading ALU function names with two accepted parameter sequences: (function) Rd, Rs1, Rs2 and (function) Rd, #Imm.

The first takes the values of Rs1 and Rs2 as inputs to the ALU and stores the result of the ALU function in Rd. The second takes the value of Rd and the immediate value #Imm as inputs to the ALU and stores the result in Rd.

Note: In practice, (function) Rd, #Imm operates as (function) Rd, Rd, #Imm, meaning Rd is used as the first argument and #Imm as the second argument. This is important for some ALU functions where order matters, such as SUB. Also, note that the immediate value #Imm is a 4-bit immediate, not an 8-bit immediate.

Assembly Instruction Use Syntax Alternate syntax Instruction it's based on Differences from instruction set Affects Flags
OR Bitwise OR OR Rd, Rs1, Rs2 OR Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) OR function has specified assembly instruction Yes
AND Bitwise AND AND Rd, Rs1, Rs2 AND Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) AND function has specified assembly instruction Yes
XOR Bitwise XOR XOR Rd, Rs1, Rs2 XOR Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) XOR function has specified assembly instruction Yes
NOT Bitwise NOT NOT Rd, Rs1, Rs2 NOT Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) NOT function has specified assembly instruction Yes
ADD Adds values of two registers ADD Rd, Rs1, Rs2 ADD Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) ADD function has specified assembly instruction Yes
SUB Subtracts value of one register from another SUB Rd, Rs1, Rs2 SUB Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) SUB function has specified assembly instruction Yes
ASL Arithmetic shift left by 1 bit ASL Rd, Rs1, Rs2 ASL Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) ASL function has specified assembly instruction Yes
ROL Rotate left by 1 bit using carry ROL Rd, Rs1, Rs2 ROL Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) ROL function has specified assembly instruction Yes
LSR Logical shift right by 1 bit LSR Rd, Rs1, Rs2 LSR Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) LSR function has specified assembly instruction Yes
ASR Arithmetic shift right by 1 bit ASR Rd, Rs1, Rs2 ASR Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) ASR function has specified assembly instruction Yes
ROR Rotate right by 1 bit using carry ROR Rd, Rs1, Rs2 ROR Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) ROR function has specified assembly instruction Yes
ADC Adds values of two registers and carry ADC Rd, Rs1, Rs2 ADC Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) ADC function has specified assembly instruction Yes
SBC Subtracts value of one register from another and adds carry SBC Rd, Rs1, Rs2 SBC Rd, #Imm ALU, opcode 2 or 6 (for alternate syntax) SBC function has specified assembly instruction Yes

Flag Setting Instructions

There are assembly instructions that use the ALU to update flags but which do not save the output of the ALU's operation. These instructions are meant to ease implementation of conditional branching by eliminating the need to overwrite a register to determine whether the branch should occur. These are listed below:

Assembly Instruction Use Syntax Alternate Syntax Instruction it's based on Affects Flags
COMP Compares register value with another register or immediate by subtraction without saving result COMP Rs1, Rs2 COMP Rs1, #Imm Test and Test immediate, opcodes 12 and 13 Yes
TST Compares register value with 0 TST Rs None Test immediate, opcode 13 (equivalent to COMP Rs1, #0) Yes

Other ALU instructions

Finally, there are some "syntactic sugar" assembly instructions that are built on-top of existing instructions. These are listed below:

Assembly Instruction Use Syntax Alternate syntax Instruction it's based on Affects Flags
INC Increments value of register by 1 INC Rd None ALU immediate, opcode 6 (is equivalent to ADD Rd, #1) Yes
DEC Decrements value of register by 1 DEC Rd None ALU immediate, opcode 6 (is equivalent to SUB Rd, #1) Yes

Branching

Like ALU assembly instructions, branching instruction names are overloaded to reflect absolute and relative branch instructions in the instruction set, opcodes 5 and 7, respectively. Hence the two supported parameter sequences are (Condition) #Imm for absolute branching and (Condition) +/-Imm for relative branching.

Absolute branching example: BEQ #5 - this will set the current line to 5 if the zero flag is high.

Relative branching example: BEQ -2 - this will set the current line to the current line minus 2 if the zero flag is high.

Important Note: Assembly instructions do differ here from the instruction set by that the specified immediate in assembly code is actually 1 larger than the compiled immediate. In absolute branching, the reason is that the line number in a text-editor is 1-indexed, while the program counter is 0-indexed. In relative branching, this is because the program counter always points at the next instruction. I.e. if the program counter fetched the instruction at address 0, it will already store the address 1 while the instruction that was loaded is being run. So for instance, intuitively JMP -1 should go to the previous line, but if implemented as is, this will actually keep the PC in place as the PC already points to the next instruction. Hence the compiled machine language code will have the immediate -2 instead.

Assembly Instruction Use Absolute branching syntax Relative branching syntax Affects Flags
JMP Unconditional jump JMP #Imm JMP +/-Imm No
BMI Branch on minus (if negative flag is high) BMI #Imm BMI +/-Imm No
BCS Branch on carry set (if carry flag is high) BCS #Imm BCS +/-Imm No
BEQ Branch if equal (if zero flag is high) BEQ #Imm BEQ +/-Imm No
BPL Branch on plus (if negative flag is low) BPL #Imm BPL +/-Imm No
BCC Branch on carry clear (if carry flag is low BCC #Imm BCC +/-Imm No
BNE Branch if not equal (if zero flag is low) BNE #Imm BNE +/-Imm No

Stack

There are four instructions in the instruction set dedicated to handling stack operations: PUSH, POP, JSR (Jump SubRoutine), and RTS (ReTurn Subroutine). ByteFrost assembly makes no significant alterations to these instructions:

Assembly Instruction Use Syntax Instruction it's based on Affects Flags
PUSH Store register on the stack and increment stack pointer PUSH Rs1 PUSH, opcode 14 No
POP Decrement stack pointer and load a register with value on the stack POP Rd POP, opcode 15 No
JSR Jump to subroutine at given address JSR #Imm JSR, opcode 16 No
RTS Return from subroutine to return address on the stack RTS RTS, opcode 17 No

Important Note: As with branching, the JSR instruction does differ from the instruction set as the specified immediate address in assembly is actually one larger than the compiled immediate. This is because the assembly program line numbers are 1-indexed, whereas in the binaries they are 0-indexed (the program counter begins at address 0, not 1).

Memory

There are multiple ways to read to / write from RAM using ByteFrost assembly. Currently these are:

Assembly Instruction Use Syntax Instruction it's based on Affects Flags
LMA Load from address to register LMA Rd, #Imm LMA, opcode 9 No
SMA Store to address from register SMA Rs, #Imm SMA, opcode 10 No
LMR Load from address in Rs to Rd LMR Rd, Rs LMR, opcode 11 No
SMR Store from Rd to address in Rs SMR Rd, Rs SMR, opcode 12 No

Examples:

  • LMA R1, #5 will load the value stored in address 5 into register R1
  • SMA R1, #5 will store the value in R1 in address 5
  • LMR R0, R1 will load the value in the address stored in R1 into R0
  • SMR R0, R1 will store the value in R0 to address in R1

Display

ByteFrost assembly includes instructions to print values to the display. The instruction name OUT is overloaded with two parameter sequences.

Assembly Instruction Use Syntax Instruction it's based on Affects Flags
OUT Prints value stored in register either as an ASCII character (with 'A' option) or as an integer (with 'I' option) OUT Rd, A/I OUT, opcode 8 No
OUT Prints immediate value either as an ASCII character (with 'A' option) or as an integer (with 'I' option) OUT #Imm, A/I OUT immediate, opcode 14 No

Printing ASCII

Using the 'A' option, the given value is printed as an ASCII character. Note that the ByteFrost display's character set is not equivalent exactly to ASCII - the character set used by ByteFrost is listed here. Additionally, the display's character set has undefined ranges, so we added our own characters to fill these (this is taken care of by the display card).

An important difference is that the values 0 through 15 print the values 0 through F in hexadecimal. This means that OUT #3, A will print 3.

There are also some derived characters which are understood only by the display card (Arduino Nano), such as the new-line character.

Printing Integers

Using the 'I' option, the given value is printed as an integer. Notice that the format for this is in hexadecimal only, so the instruction OUT #5, I will be printed as 05 on the display.

Miscellaneous

Miscellaneous instructions that don't fit any other category are listed below:

Assembly Instruction Use Syntax Instruction it's based on Differences from instruction set Affects Flags
NOP No operation NOP NOP, opcode 0 No difference No
BRK Halt operation BRK BRK, opcode 1 No difference No