Notes on Assembly Language Brief introduction to assembly programming The main components of a computer that take part in the execution of a program written in assembly code are the following: A set of registers: Input: a binary register that stores the binary input number provided by the user Output: a binary register that stores the binary output number provided by the system to the user. Accumulator: a binary register that stores a binary number provided either from the main memory or from the input. Program Counter (PC): a binary register that carries the memory address of the next instruction to be executed. Instruction Register (IR): a binary register that carries the binary code of the instruction that is currently being executed. Main memory: A set of memory cells where binary information is stored. Each memory cell has a unique address that determines it. Addressing starts from number 0, i.e. the address of the top memory cell is 0, the address of the next one is 1, etc. An assembly instruction has two parts: the opcode and the operand. The opcode describes the command that is to be executed and the operand is: 1) the address of a memory cell, or 2) a numeric value. Basic OPCODES supported by the Super-Simple CPU Binary Mnemonic Short Explanation ---------------------------------------------------------------- 1111 STP Stop the computer 0001 ADD Add accum. to operand 0010 SUB Subtract operand from accum. 0011 LOD Load memory cell into accum. 0100 LDI Load immediate into accum. 0101 STO Store accum. into memory cell 0110 INP Input value and store into accum. 0111 OUT Output the value from accum. 1000 JMP Jump to instruction 1001 JNG Jump to instruction if accum<0 1010 JZR Jump to instruction if accum=0 The operand of commands INP, OUT, STP is always zero (0).
Basic program execution A program written in assembly is further converted to machine language, i.e. the language that the CPU understands. Each instruction (now in binary format) is loaded to main memory. Each memory cell contains one instruction. The program counter (PC) is set to the memory address of the first command, e.g. 0. The program instruction-by-instruction base on the fetch-execute cycle. Fetch-Execute Cycle 1) Read value in PC and go to that memory cell. 2) Fetch the instruction written in that memory cell and bring it to IR. 3) Translate the instruction in IR and execute it. 4) Increase PC by 1. 5) Go back to step 1 until you reach the end of the program. Example 1: Write a program in assembly that takes a number from Input and writes it to the Output. 1) 2) OUT 0 3) STP 0 Example 2: Write a program that takes two numbers as input and writes their sum to the output. Notice that all available commands transfer data from Input to ACC, from ACC to output, from ACC to memory and from memory to ACC. The only way of writing a valid program is to use the available commands. Let s think in terms of pseudo-code first (pseudo-code: analyze the program into smaller steps and write in simple English what each step should do). Pseudo-code 1) get first number from input 2) store number in ACC 3) get second number from input 4) store first number in memory before storing the new one in ACC 5) add number in ACC to number in memory 6) store result in ACC 7) bring result from ACC to output 8) stop the program Now let s convert the above list of instructions to assembly code:
A) B) C) D) E) OUT 0 F) STP 0 Notice that each pseudo-code instruction does not necessarily correspond to one assembly command. Pseudo-code is the way each individual approaches the solution to the problem whereas Assembly is fixed and the instructions it supports are standard. Example 3: Write a program that takes three numbers as input and writes their sum to the output. A) B) C) D) E) F) G) H) OUT 0 G) STP 0 Example 4: Write a program that takes N numbers as input and writes their sum to the output. Notice that in the previous solution there is a repetition of three commands: The repeated code gets a new number from the Input adds the current sum (which is stored in memory cell 15) to the ACC and then stores the new sum back to memory cell 15. Let s try to do that using some more Assembly commands. JMP X: this command will set the PC to point at the instruction that is labeled as X (if X is a set of characters), or it will set the PC to point to the instruction that is in memory cell X (if X is a number). Labeling Before each Assembly instruction we can add a word that corresponds to the label of that instruction, i.e.
BEGIN BEGIN is a label for instruction. Then if we use JMP BEGIN at some point the code, the PC will jump to that instruction and will continue the program execution from that instruction and on. Immediate setting DAT X: this instruction will place the numeric value X to the memory cell where this instruction is loaded. For example, if the 5 th line of the Assembly program has the following command: DAT 4, then memory cell 5 will have value 4. LOD X: this instruction will go to memory cell X and it will load the value in that cell to the ACC. LDI X: this instruction will place the numeric value X to ACC. Jump under a condition JZR X: Jump to label X if the value stored in ACC is zero. Let s go back to our problem now. Take a look at the following code: We saw that this code should keep repeating itself for each new number we want to add. Why don t we use a JMP instruction to make the code repeat many times? Notice that we have added a label called LOOP at the first instruction of the piece of code that is to be repeated. The above code will keep repeating itself: it will keep asking for a new number, add it to what is stored in memory cell 15 and finally store the new sum to the same memory cell. So, what we have achieved so far is to write a program that takes an infinite amount of inputs, adds them and stores them in memory cell 15. We need to find a way to make the program count how many times to perform that loop. Put another way, we want to give the program a number as input, say N, and have the program ask us for N numbers to add, and finally produce their sum. Let s add two more lines to the code above:
The first two lines ask for an input number and store this number in memory cell 14. This cell will contain the number of values that we want to add, i.e. the number of times we want to perform the loop. Then we have to find a way of stopping the loop after it is executed as many times as the number stored in memory cell 14. We can do that using the following trick: every time the loop is executed, we reduce the value of the number in cell 14 by 1. When that number becomes zero (0) we can stop the loop. The instruction we are going to use for counting down is SUB. SUB X, subtracts the value stored in memory cell X from ACC and stored the result back to ACC. Every time we need to subtract 1, thus we have to store this value in memory. ONE DAT 1 We have added one more command at the very end. The label of this command is ONE and it just stored number 1 in the memory cell where the command resides. Finally let s perform the subtraction LOD 14 SUB ONE
ONE DAT 1 So, every time we add a new number we perform three more instructions: 1) LOD 14: load whatever is in memory cell 15 to ACC (in memory cell 14 we store the number of loops we want to execute). 2) SUB ONE: go to memory cell that corresponds to label ONE (i.e. to memory cell with value 1) and subtract the value stored in that cell (i.e. 1) from what is in ACC. 3) : store the new number (old value reduced by 1) back to memory cell 14. We are almost done! All we need to check is whether ACC is zero. If so the loop has been repeated as many times as we want, so we can jump outside it. LOD 14 SUB ONE JNZ DONE ONE DAT 1 DONE LOD 15 OUT 0 STP 0 Three last instructions have been added: 1) JNZ DONE: if the current value in ACC is zero, jump to the instruction with label DONE. 2) When we go to the DONE label (notice that it is below the JMP command), we load the value in memory cell 15 (i.e. the current sum of all numbers that have been added), LOD 15, into ACC 3) Finally, we output the value, OUT 0, and stop the program, STP 0. Example 5: How can we multiply two numbers? Given two numbers, X and Y, we want to calculate X*Y. But wait! Isn t that equivalent to adding number X to number X, Y times? For example, say you want to multiply number 3 with number 4. But, 4*3 equals 4 + 4 + 4. So this is like adding number 4 to number 4, 3 times!