A good place to start on the next part is a bit difficult. Striking the proper level of abstraction is harder than I thought.
Real processors would have much more sophisticated, ISAs and machine models. There is also an issue with Big Endian vs. little endian, stack-pointers, segments, etc. that I am excluding from this model.
But, for illustration purposes, lets say our Instruction Set Architecture (ISA) is the following (completely made up and rather impractical):
opcode 0x0: HALT # halts the processor
opcode 0x1: BNZ <register> <label> # Branch to <label> if the value in <register> is not 0
opcode 0x2: ADD <register1> <register2> # Add the value of <register2> to <register1> and store the result in <register1> (old value lost)
opcode 0x3: SUB <register1> <register2> # Subtract the value of <register2> to <register1> and store the result in <register1> (old value lost)
opcode 0x4: AND <register1> <register2> # And the value of <register2> to <register1> and store the result in <register1> (old value lost)
opcode 0x5: OR <register1> <register2> # And the value of <register2> to <register1> and store the result in <register1> (old value lost)
opcode 0x6: SHL <register> <constant> # shift the value in <register> by <constant> (between 0 and 8) for this instruction.
opcode 0x7: ROR <register> <constant> # rotate the value in <register> by <constant> (between 0 and 8) for this instruction.
opcode 0x8: LDC <register> <constant> # load <constant> (0 to 255) into <register>
opcode 0x9: RDM <register1> (<register2>) #read the value stored at the address denoted by the value stored in <register2> to <register1>
opcode 0xA: WRM (<register1>) <register2> #write the value in <register1> into the location specified by the address in <register2>
opcode 0xB: IN <register> <port> # read a port
opcode 0xC: OUT <port> <register> # write a port
Note: 4-bit opcode used for each instruction.
So the instruction format is a 20-bit format:
4-bits opcode, followed by 8-bit operand 1, followed by 8-bit operand 2.
We have the following general registers:
A,B, C, D (make them all 8-bit registers for now).
Register Codes (2-bits):
A:0x0, B:0x1, C:0x2, D:0x3
When a register is an operand, only the 2 least significant bits are used.
Lets say you have 2 I/O ports:
IO_A (port code 0) is an 8-bit port where if you write there, two 7-segment LEDs will display the value written in hexadecimal. When you read that port, you will get back the last value you wrote. On Power-on, that port will initialize to 0x00 (hexadecimal for all 8-bits being 0)
IO_B (port code 1) is another 8-bit port hooked up to 8 2-pole on-off switches (numbered 7 down to 0). When you read this port, you get back a binary value (which we will generally short-hand use hexadecimal values) representing which switches are on. Getting back 0x01 means switch 0 is on, and all the rest are off. Getting back 0x02 means switch 1 is on, and the rest are off. Getting back 0x03 means switches 1 and 0 are on, and all the rest are off. ... Writing this port does nothing.
When a register is an operand, only the least significant bits are used.
Lets say you can address 2^8=256 memory locations (all "well-behaved," i.e. not memory-mapped I/O). Lets further say that this space is only available for "data" that your programs will read and write from and to.
Lets pretend there is is this magical "code space" where all the instructions of you program sits, and you can program this space with an external programmer.
Once the external programmer is done, it resets a special purpose register called the "Program Counter" to 0. All your programs are placed in code-space with the first instruction at 0. Lets assume that an 8-bit Program counter is enough.
Believe it or not that is about as simple as I could make the model anticipating the type of stuff I want to include in the next few brain-dumps.
Now lets translate the some Assembly to machine code.
The Assembler Code will cause memory locations 0x0 through 0xA to have the values 0x0 through 0xA, and the 7-segment display to count down from 0xA to 0x0:
LDC A 0xB
LDC B 1
L1:SUB A B
WRM (A) A
OUT IO_A A
BNZ A L1
HALT
Machine Code:
0:0x8000B
1:0x80101
2:0x30001
3:0xA0000
4:0xC0000
5:0x10002
6:0x00000
Lets see if you understood this (completely made-up) machine model and the example translation (hopefully I didn't make mistakes). If so, I can walk you through what happens to the registers, memory and ports, step by step.
__________________
sloan+ Rxua|I|; primary Inquisitive; R(82%)L(52%)U(62%)A(54%)I(86%)
CTO of IPTN (see Maverick's Sig.) and member of Maverick's Biker Club.
Accept the past. Live for the present. Look forward to the future.
My Blog
I linked some of your blogs; if you feel that is inappropriate, please let me know.
|