In this course, there will be opportunities for advanced students to gain greater understanding of the functioning of a computer while not overloading the schedules of those students who are new to programming.
One of those opportunities is understanding the machine instructions to which the programs written in C++ are converted to. Machine instructions are all binary numbers, and thus to make them human readable, we will introduce an intermediate assembly language where each assembly instruction corresponds to a machine instruction, only in human-readable form.
Assembly language must be necessarily precise, as you must be able to specify if you are performing operations on one, two, four or eight bytes, for example, and there are many instructions covering specific commands the purpose of which is not clear in first year, and they tend to be reasonably terse:
For example, an interesting site that shows MIPS assembly language examples is provided by an excellent web site at the Paul G. Allen School of Computer Science and Engineering at the University of Washington:
Given this for-loop,
for ( size_t i = 0; i < capacity; i++ ) { A[i] = MAX_SIZE; }
an unoptimized for loop in assembly language is:
add $t0, $gp, $zero # &A[0] - 28 lw $t1, 4($gp) # fetch N sll $t1, $t1, 2 # N as byte offset add $t1, $t1, $gp # &A[N] - 28 ori $t2, $zero, 256 # MAX_SIZE top: sltu $t3, $t0, $t1 # have we reached the final address? beq $t3, $zero, done # yes, we're done sw $t2, 28($t0) # A[i] = 0 addi $t0, $t0, 4 # update $t0 to point to next element j top # go to top of loop done:
We will try to make this more human-readable, although by third year, you should be very familiar with the above code:
Instruction | Description |
---|---|
ADD Di + Dj -> Dk | Add data registers 'i' and 'j' and put the output into data register 'k' |
ADD Di + 'n' -> Dk | Add the value 'n' to data register i and put the output into data register 'k' |
SUBTRACT Di - Dj -> Dk | Subtract data register 'j' from 'i' and put the output into data register 'k' |
MULTIPLY Di * Dj -> Dk | Multiply data registers 'i' and 'j' and put the output into data register 'k' |
MULTIPLY Di * 'n' -> Dk | Multiply the value 'n' by data register i and put the output into data register 'k' |
DIVIDE Di / Dj -> Dk | Divide data register 'i' by 'j' and put the output into data register 'k' |
Like C++, you have to have some form of flow control; however, in assembly language, the natural flow control is essentially a goto statement: go to the instruction with a specified label:
Instruction | Description |
---|---|
BRANCH Di == Dj goto LABEL | If data registers i and j are equal, branch to the label 'LABEL' |
BRANCH Di == 'n' goto LABEL | If data register i and 'n' are equal, branch to the label 'LABEL' |
BRANCH Di != Dj goto LABEL | If data registers i and j are not equal, branch to the label 'LABEL' |
BRANCH Di != 'n' goto LABEL | If data register i and 'n' are not equal, branch to the label 'LABEL' |
BRANCH Di < Dj goto LABEL | If data register i is less than data register j, branch to the label 'LABEL' |
BRANCH Di < 'n' goto LABEL | If data register i is less than 'n', branch to the label 'LABEL' |
BRANCH Di <= Dj goto LABEL | If data register i is not greater than data register j, branch to the label 'LABEL' |
BRANCH Di <= 'n' goto LABEL | If data register i is not greater than 'n', branch to the label 'LABEL' |
BRANCH Di > Dj goto LABEL | If data register i is greater than data register j, branch to the label 'LABEL' |
BRANCH Di > 'n' goto LABEL | If data register i is greater than 'n', branch to the label 'LABEL' |
BRANCH Di >= Dj goto LABEL | If data register i is not less than data register j, branch to the label 'LABEL' |
BRANCH Di >= 'n' goto LABEL | If data register i is not less than 'n', branch to the label 'LABEL' |
BRANCH goto LABEL | Branch unconditionally to the label 'LABEL' |
RETURN-FROM-FUNCTION | Branch unconditionally to the the point from which the function is called |
All machine instructions related to logical operations are bit-wise, meaning the operation is applied to each of the bits.
Instruction | Description |
---|---|
AND Di & Dj -> Dk | Take the bit-wise 'and' of registers 'i' and 'j' and put the output into data register 'k' |
AND Di & 'n' -> Dk | Take the bit-wise 'and' of register 'i' and the value 'n' and put the output into data register 'k' |
OR Di | Dj -> Dk | Take the bit-wise 'or' of registers 'i' and 'j' and put the output into data register 'k' |
OR Di | 'n' -> Dk | Take the bit-wise 'or' of register 'i' and the value 'n' and put the output into data register 'k' |
XOR Di ^ Dj -> Dk | Take the bit-wise 'xor' of registers 'i' and 'j' and put the output into data register 'k' |
XOR Di ^ 'n' -> Dk | Take the bit-wise 'xor' of register 'i' and the value 'n' and put the output into data register 'k' |
NOT ~Di -> Dk | Take the bit-wise 'not' of register 'i' and put the output into data register 'k' |
The logical operations of &&, || and ! can be achieved by restricting the values stored in the data registers to either 0 or 1.
Address registers store the addresses of data or addresses stored in main memory. All data or addresses must be loaded into registers first before they are operated on.
Instruction | Description |
---|---|
LOAD (Ai) -> Dk | Load the value at address in address register 'i' and save it to data register 'k' |
LOAD (Ai + Dj) -> Dk | Load the value at address in address register 'i' offset by data register 'j' and save it to data register 'k' |
STORE Di -> (Aj) | Store the value in data register 'i' to the address in address register 'j' |
STORE Di -> (Aj + dk) | Store the value in data register 'i' to address in address register 'j' offset by data register 'k' |
WRITE 'n' -> Dj | Store the value 'n' in data register 'j' |
In your second-year courses, you will start to look at various instruction sets. For example, Intel processors will use a different set of instructions than ARM processors which will differ again from instruction sets for Motorola processors, and different processor families within these companies will have different, but still recognizably similar, instruction sets. All of these instruction sets are proprietary, so one common non-proprietary instruction set is MIPS. This is the instruction set we are using as a basis for our easier instruction set above.
You can view the actual MIPS instruction set at this clean website from the University of Idaho.