How could you get the loader to load into code memory, data memory, and maybe even stack memory?
We could use a different S record type..
S1 code
S2 data
S3 stack
or something like that...
We stat with instructions and data and hte loader puts them into memory.
S records tell us information about where to store the data
We now have code and data in our machine. We need to know where we start.
Once we know the starting address, the program runs
We need the CPU
We also require the bus
We also require devices
Our instructions have a format: opcode and operand(s)
The opcodes are the instructions to the machine and the operands are the data
We can have zero address instructions (typically on a zero address machine)
When we talk about x-address instructions we are susually talking about arithmetic instructions
e.g. ADD
If zero address, we can assume it's a stack machine.
We can have one-address, in which case you're probably dealing with an accumulator + memory
The accumulator operates on a memory location
We can also have 2-address instrcuions. It's data that we're working with and what we have is DST = DST + SRC
In a 2 address machine, the quiestion is where is the dstination and where is the source
in our case we only have register register
we can also have register memory
meory register
and memory memory
What's the beauty behind register register? it's fast because it's already in the cpu. Things only require 1 fetch
In the other extreme, memory-memory, we would need three memory accesses. We have to fetch the instruction, then fetch the source, then fetch the destination, then write back to memory. so actually 4 memory accesses but 3 fetches.
We have different formats of isntructions that aredifferent depending on the ISA
To access instructions we requre the PC. what does the PC have? the addres of the next isntructions. Now what takes place internally is we want to execute things, and in order to do that we start the instruction cycle which is Fetch, Decode, Execute.
Fetch gets the next instruction
Let's fill in some blanks abotu the CPU:
we require a memoery address register, a memory data register, a memory buffer register. we also require a control bit. this specifies to memory what we want to do: either read or write.
The MAR goes int othe instruction register
The IR goes into the decoder
The instruction, which consists of the opcode and operand, has to be decoded. The decoding then tells the execution unit what the instruction is
In a one addrss machine, we require index registers
If we have an array, it would be something like A = A + data[i]
The index register allows us to access this memory, because when we have our block ofmemory (array), each data value is associated with an address. if weh ave an index regiseter, it gives us that address. On a one address machine, that allows us to do this with an accumulator:
ADDA [IX] ← use IX as the address of a memory location
The address would go out to memory, the data wouldbe returned and added to memory
What's the advantage of the index register?
using just data would be static value that can't change. However with an instruction register the data is an address that can change
In a two address machine we proobably have general purpose registers. and the GPR allow us to do either arithmetic (as an accumulator) or use it for indexing (accessing memory)
GPR are stored in the CPU because they're faster compared to accessing memory since we don't have to access the bus
All of the machine's register are stored in the register file.
What is the RF? it's a small memory
Each register can hold an arithmetic result, or an index or an address
If we have a 2 address machine, tpyically we would be adding 2 registers together, they are both stored in the register file. We have an ALU that takes two inputs from the register file.
The alu will get a function, determined by the opcode and sent to the control unit.
The result of the ALU goes back into the register file. The typical outputs are the result and the status bits.
The status (PSW) consists of several bits, the ones we are interested in are
V Overflow - arithmetic operation - signed operation. Two negative numbers have become positive or vice versa
N Negative - If the MSB is set. The machine doesn't know whether it's signed or unsigned arithmetic, it just reports the state of the data
Z Zero
C Carry - unsigned arithmetic
We have sequential operations, conditional, looping
Sequential: control flows to the bottom of the page
Conditional: flow of control can change
Looping:
We have deterministic, in which we have a lower bound and an upper bound
Pre test, you test the condition before you enter the loop
post test, test the condition after the loop is performed once (end of the loop)
There are special instructions to do this because whenever we want to change the flow of control, we require state changes. We can use the status bits in the PSW for that.
Typical operations are combinations of those bits, such as A == B, A > B (boolean operations)
These are implemented using lower level instruction such a BEQ BNE BLT...
These use the PSW(status bits) to make a decision
What happens then? when these instructions are encountered we check the status bits
To change the flow of control, we check the status bits and either change the PC or not.
We also have an unconditional branch which allows us to always change the flow of control without changing or looking at the status bits
What if we want to call a subroutine that is outside of our main program?
Subroutine requires 2 things:
Entry point
(follows by its own isntructions and data)
Return
address of the next instruction
Handling the return address can be done with a stack, or a specific register (link register)
What's nice about the stack is that you can next your subroutine calls.
What's nice about the link register is that it's much faster
We also need a way of getting values out of the machine and into memory or out intto the outside world
So we need isntructions to access memory. Read/write
To access data we need an address.
We also require special instruction... LOAD and STORE
What do these require? a source and a destination
LD: src would be an address, dst is probably a register but some machines could allow u to move directly to aanother mem address
ST: src: again probably a register, dst: address
We have different ways of addressing. We can have
Absolute addressing
Relative addressing
Struct → contains fields. If we have the base address, we can have relative addresses for each field.
Indexed
Typically used for arrays. Allows us to move through an array
We also need devices
Devices are used for communicating with the machine... usually fall into either input or output.
If we have a generic device, and we have our CPU, what can the CPU do to a device? Either read from it or write to it.
The CPU can control the device (program it) saying that we want certain behaviours
Status also flows from the device to the CPU so it can tell it when it gets a state change
How do we know when the device changes state?
We can poll it... but that wastes CPU cycles
We can also have interrupots
If we have a generic device, and we have our CPU, what can the CPU do to a device? Either read from it or write to it.
The device also has memory
We also introduced cache. Between CPU and primary memory, we put a cache in there. Smaller than primary memory, the cache is fast.
A cache line has an address, contents (instructions or data),
if cex is not set, ig nore it (decode execute)
else
if do then
if exec then decode
true count --
if true count = 0
state = do exicute?
else if fo else
if exec then
ddecode and execute
false count --
if fc = 0 then
state = something
> ignore
> do then
> do else Index