We're looking for your comments on how to best organize the wiki's content.

Assembly beginner's guide

From 0x10c Wiki
Jump to: navigation, search

This guide is for people who have little to no knowledge of programming in assembly. For a more rigorous overview of DCPU-16 assembly, see assembly language syntax.

A lot of details are skipped, in an attempt to get a rudimentary understanding as quickly as possible. You may want to use an assembler while going through this tutorial.

Contents

[edit] Memory

[edit] Words

In computer science, "word" has a very different meaning than in the English department. A "word" in computer science is a block of memory which can contain a single number. In the case of the DCPU-16, each word is 16 bits. This means that the maximum value of a number in a single block of memory on the DCPU-16 is 2^16 - 1. (-1 because we include 0) In other words, word sized numbers on the DCPU-16 have the range [0, 65535] in decimal.

An example of a 16 bit word is: "0011 0000 0011 1001" which is equivalent to the number 12,345.

[edit] Storage

There are two places you can use for memory on the DCPU-16: Registers and the Stack.

[edit] Registers

Inside the processor itself, there exist 11 registers. A register is a block of memory which can store a single word. Because the registers are inside the processor, they can be accessed very quickly, as opposed to RAM. Each register has a name. On the DCPU-16, these names are: A, B, C, X, Y, Z, I, J, PC, SP, EX, and IA.

A, B, C, X, Y, Z, I and J are general purpose registers. You can use them to do any calculations you want. PC (Program Counter,) SP (Stack Pointer,) EX (Excess or Extra,) and IA (Interrupt Address,) are special registers. Their purposes will be explained later in this tutorial.

[edit] Stack

The stack is used to store and load data from RAM. It is necessary to use the stack if you want to do calculations, but have used up all your registers. The SP (Stack Pointer) register always holds the address of the top of the stack, but this is an advanced feature we will discuss later.

[edit] Instructions

Main article: Instruction set

Each line of code in DCPU-16 assembly corresponds to one instruction. An instruction is usually a single basic calculation. One line of assembly also corresponds to a single line of code in pure binary. In this article, only the simplest instructions will be presented.

[edit] SET instruction

The SET instruction simply sets the value of a register to a given value. The format is: SET Register_Name, Value

Example:

SET A, 5

This sets the value in register A to 5.

[edit] Arithmetic instructions

ADD, SUB, MUL and DIV are used to do simple math. They stand for "add", "subtract", "multiply" and "divide", respectively. In other words, they correspond to the symbols + (plus), − (minus), × (multiply), / (divide). You can use them like so:

This will increase the value in A by 5

ADD A, 5

This will reduce the value in A by 5

SUB A, 5

This will multiply the value in A by 5

MUL A, 5

This will divide the value in A by 5

DIV A, 5

EXERCISE 1:

The task: Calculate 5 + 40 − 3 × 12 and store the result in register A

SET A, 5
ADD A, 40
SET B, 3
MUL B, 12
SUB A, B

Note the attention to order of operations.

Read this program line by line, and write down on paper what the values in A and B are at each line. Check your understanding by comparing your values with those in the solutions at the end of this article.

[edit] Conditional execution

Sometimes you might want to only execute an instruction if a certain condition is true. This can be done by using the IFE, IFN, IFG instructions. They stand for "If Equal", "If Not Equal", and "If Greater" respectively. If the condition specified is not true, then the next instruction will be skipped.

EXERCISE 2:

SET A, 3
SET B, 3
IFE A, B
SET C, 10
IFN A, B
SET C, 0
IFG C, 0
SET A, C

What are the values of registers A, B, C after this program ended?

Trace through and write down your answers, then check the solution at the end of this article.

[edit] Comments

As you can probably guess from the last two exercises, it's easy to become lost because your variables don't have meaningful names. To resolve this problem, you can add comments to your code to help readers understand it.

Comments are denoted by the character ';'. If you put this character in your code, everything after it will be ignored.

Example:

SET A, 107
;Limits the value of A between 20 and 100
IFG 20, A ; if 20 > A, A = 20
SET A, 20
IFG A, 100 ; if A > 100, A = 100
SET A, 100

[edit] Labels and branches

Your program may not be linear. You may need to loop over some code many times, or you may want to suddenly quit your program. This can all be done using labels. Labels are a way of giving a name to a certain line in your program. After giving a line a label, you can jump your execution to it. The current line of code you are reading is always automatically stored in the PC (Program Counter) register. The processor will automatically update the value of the PC each time a new instruction needs to be read. However, you may manually modify the value of the PC to a label in order to jump your execution to it.

Labels are declared as such:

:mylabel

You can jump to this label using this code:

SET PC, mylabel

Note that the order in which labels are created does not matter. You are allowed to jump to a label further ahead in the code.

EXERCISE 3:

SET A, 2
SET B, 0
:loop_start
IFE A, 0
SET PC, loop_end
ADD B, 7
SUB A, 1
SET PC, loop_start
:loop_end

As usual, read the code line by line while writing on paper the value of A and B as they are modified. Check your answer at the end of the article afterward.

[edit] Subroutines

Main article: Subroutines

You might want to reuse some code many times. One way of doing this is by storing it in a subroutine. Subroutines are denoted the same way as labels. To jump into a subroutine, use this instruction:

JSR mysubroutine

A basic subroutine has this format:

:mysubroutine
; some calculations can be done here
SET PC, POP

SET PC, POP on the final line of mysubroutine is what denotes the end of the subroutine and returns the execution to its previous location on the line after the JSR call. If you forget to write this line, you will experience some very weird bugs.

Here is an example of a subroutine in action:

SET A, 4
JSR squared
SET PC, halt
 
; sets the value in A to A squared
:squared
MUL A, A
SET PC, POP
 
; if you set the PC to the same line it currently is at, the program will end.
:halt SET PC, halt

Again, step through the code line by line and make sure you understand everything.

[edit] Accessing memory

At this point, the tutorial becomes a little more advanced. Drink another cup of coffee and keep on reading more attentively! You might need more explanations on certain concepts if you haven't programmed in a language like C or another assembly before.

The value inside a register may be an address of a variable in RAM, rather than the actual value of the variable. In order to access the value at that address, you can use the notation [A] (using register A as an example)

Example:

SET [0xC000], 5 ; set the value AT the arbitrary address 0xC000 in memory to 5
SET A, 0xC000 ; set A to the value 0xC000, which is 49152 in decimal (NOT the value at 0xC000)
SET B, [A] ; set B to the value AT the address stored in A

Note that while you are allowed to access the memory at any arbitrary address, you should not normally do it. Some places in memory are reserved for certain tasks, and you can't be sure that you aren't using memory which is already used somewhere else.

[edit] The stack

Main article: Stack

The stack is your main access point to memory. The stack follows LIFO (Last In First Out) behaviour. In other words, it works like a tower: You can only add new blocks to the top of the tower, or remove blocks from the top of the tower. Adding blocks is known as "pushing", and removing blocks is known as "popping". The DCPU-16 is also capable of "peeking", a nonstandard operation that looks at the top block without removing it.

When you push a word on the stack, the SP will decrease by 1. When you pop a word from the stack, the SP will increase by 1. You can therefore unwind the stack simply by performing ADD operations on the stack.

The stack's main use is to store local variables without hogging registers. The special register SP (Stack Pointer) is used to remember where the top of the stack is. You can therefore use it to access variables on the stack. Here is an example of using the stack to store variables:

EXERCISE 4:

SET PUSH, 10 ; push the number 10 on the stack
SET PUSH, 5 ; push the number 5 on the stack
SET B, 7
SET PUSH, B ; push value in B on stack
SET A, PEEK ; set A to value AT top of stack.
SET B, 3
SET B, POP ; pop value at top of stack and store in B
ADD SP, 1 ; remove 5 from the stack by moving stack pointer down
ADD SP, 1 ; remove 10 from the stack by moving stack pointer down
; stack is now clean

Trace through the code in this example, while drawing what the stack looks like at every line and noting what the value of B is. Check your answer at the end of this article.

Note that for the last two lines in the last example, it is not necessary to specify the number which you want to pop. In the official specification, it says "If any instruction tries to assign a literal value, the assignment fails silently. Other than that, the instruction behaves as normal." I only chose to use 5 and 10 for clarity.

[edit] Proper functions

Since you only have 8 general purpose registers, it's easy to run out. You must use the stack to make sure that calling a function does not affect registers you don't want to change. Advanced readers should read the Calling convention to write functions with standardised behaviour.

The gist of it is that you might want to reduce side-effects in functions. For example, you might need to use register X in your calculations in a function, but you don't want to mess up the value that was in it before the function call. This problem can be remedied by pushing X onto the stack before doing anything in your function, then popping it after.

Example:

SET X, 2
JSR do_calc
; A now has value of 5 + 40 - 3 * 12
; X has retained value of 2 across the function call
:halt SET PC, halt
 
; calculates 5 + 40 - 3 * 12 and stores the result in A
:do_calc
; function prologue
SET PUSH, X
SET PUSH, Y
 
SET X, 5
ADD X, 40
SET Y, 3
MUL Y, 12
SET A, X
SUB A, Y
 
; function epilogue
SET Y, POP
SET X, POP
SET PC, POP

After seeing functions, subroutines, and the stack, can you figure out the purpose of the "SET PC, POP" at the end of functions and subroutines? Here's a hint: the JSR instruction does two things: First, pushes the address of the instruction after the JSR on the stack, then sets the PC to the specified label.

[edit] What next?

Practice a bunch! Write some small programs and test them out using the emulators people have written so far. You also should read the Official Specification in detail. It's the best place to look up details about what does what.

[edit] Feedback

The easier this article is to understand, the better. Please send feedback about this article to nlguillemot@gmail.com, and I'll do my best to answer your questions and make this article better for new readers.

[edit] Solutions to exercises

Don't read if you haven't done the excercises!

Exercise 1:

  • A: 9
  • B: 36

Exercise 2:

  • A: 10
  • B: 3
  • C: 10

Exercise 3:

  • A: 0
  • B: 14

Exercise 4:

Before first line:

[             ]

after line 1:

[           10]

after line 2:

[         5 10]

line 3: B now has value 7

after line 4:

[       7 5 10]

line 5: A now has value 7 (value AT top of stack)

line 6: B now has value 3

after line 7:

[         5 10]

B also now has value 7

after line 8:

[           10]

after line 9:

[             ]
Personal tools
Namespaces
Variants
Actions
Navigation
Community
Toolbox