There needs to be some way to represent negative numbers in a processor. There are a few goals to do so:
Two's complement achieves this.
Simply, flip all of the bits and add one to the number.
$$[-2^{b-1}, 2^{b-1} -1]$$
Often, in a processor, you want to move a value stored in a smaller register (such as a 4-bit register), to a larger register (say 8 bits). Obviously, you wouldn't want to change the value. To do this, you pad the number with the most significant bit.
As a recap, an ISA defines a set of instructions that programmers can use to make the processor do what they want. Computers store instructions the same way they store data: as strings of ones and zeros.
Each instruction is encoded in memory, and the converted to a number.
load
and store
commandsTons of options, because it makes it easier for the programmer to navigate through gigabytes of memory.
Specifying the address directly. Address is specified in the instruction, almost as an immediate operand to the instruction.
To move the value in memory at 1500 to r1:
load r1, M[1500]
jump M[3000]
. Basically a goto
command.Specify an immediate address, load the value from that immediate address, and then load the value from that reference address.
load r1, M[ M[1900] ]
Very similar to pointers in C.
Specify which register has the reference address.
load r1, M[r2]
Very similar to an array in C. Also, helpful because it is faster than indirect addressing.
Similar to register indirect, but with an offset which is an immediate constant which is stored in an instruction.
load r1, M[r2 + 1000]
Good for accessing class objects/structures. Say you want to address every second field of the following structure:
struct ints {
int a;
int b;
}
If r1
had the address of the struct, then r1 + 4
would give you the address of the b
field. If you wanted to skip the whole struct, you could say r1 + 8
since both int
s take up 4 bytes in memory.
A variant on base + displacement. Addressing relative to your program counter (PC). For example, consider the following instruction:
jump [-8]
This would mean that the program counter jumps ahead two instructions. This would be useful in the following if
loop:
if (x) {
// one instruction
// another
} else {
// the rest that you actually want
}
LC2k is a more simplified architecture.
and
(and)nand
(not and)lw
(load word)sw
(store word)beq
(branch equal)jalr
halt
(end program)noop
(no operation)add
, and nand
)lw
, sw
, beq
)Three main types of instructions:
Limitation of assembly language: the number of source operands has a max of 2. This means you have to break down a complex expression down into simpler ones.
f = (g + h) - (i + j)
Where g = r3, h = r4, i = r5, j = r6. This is a way to do the addition:
add r1, r3, r4
add r2, r5, r6
sub r7, r1, r2
In many commands, such as add
, the second operand can either be a register OR an immediate.
Some interesting commands:
LSR
: logical shift right (also there is one for left).ROR
: moves the value to a 32-bit register, and shifts by 8 bits. Used for expressing numbers greater than 8 bits.