Twenty Three Hundred
Dr Charles Martin
Semester 1, 2022
What was this course about again?
All gates can be represented by NAND or NOR.
The basic idea: define (binary) negative numbers so the adder works.
How do we make a number negative? Invert bits and add one! Why does that work?
What’s the difference between Boolean algebra, combinational logic, and sequential logic?
Why do we need all three of these things to describe computers?
Are there parts of the story missing from this course?
What are the main components of a CPU?
Can you explain what each of these components do?
We come back to this later…
This status flag is set when the result of an ALU operation is negative if interpreted as a twos complement signed integer
movs r0, 5
movs r1, 6
subs r2, r0, r1
don’t forget the s
suffix
This status flag is set when the result of an ALU operation is zero
movs r5, 5
movs r6, -5
adds r4, r5, r6
This status flag is set when the result of an ALU operation requires a “carry out” if interpreted as an unsigned 32-bit integer (i.e. it requires 33 or more bits to represent)
movs r2, 0xFF000000
movs r3, 0xFF000000
adds r5, r2, r3
This status flag is set when the result of an ALU operation would overflow the min/max value if interpreted as a twos complement signed integer
movs r0, 0x7FFFFFFF @ largest signed integer
adds r0, 1
movs r0, 0x80000000 @ smallest signed integer
subs r0, 1
movs r0, 5
movs r1, 6
subs r2, r0, r1
What flags will be set after the subs
instruction is executed?
Instructions are either:
What does this mean for the programmer?
Load:
mov r1, 0x20000000 @ put the address in r1
ldr r0, [r1] @ load the data into r0
Store:
mov r0, 42
mov r1, 0x20000000
str r0, [r1]
Load less than 32 bits
ldrb @ load byte from register
ldrh @ load halfword from register
strb @ store byte to register
strh @ store halfword to register
Negative Stack
stmdb <Rs>!, {Rgstrs} @ store multiple decrement before
ldmia <Rs>!, {Rgstrs} @ load multiple increment after
push {Rgstrs}
pop {Rgstrs}
beq <label> @ branch if Z = 1
bne <label> @ branch if Z = 0
bcs <label> @ branch if C = 0
bcc <label> @ branch if C = 1
bmi <label> @ branch if N = 1
bpl <label> @ branch if N = 0
bvs <label> @ branch if V = 1
bvc <label> @ branch if V = 0
bl
, bx
, and lr
sp
and fp
)The ARMv7 Architecture Procedure Call Standard is the convention we’ll (try to) adhere to in programming our microbits
The full standard is quite detailed, but the general summary is:
r0
-r3
are the parameter and scratch registersr0
-r1
are also the result registersr4
-r11
are callee-save registersr12
-r15
are special registers (ip
, sp
, lr
, pc
)@ Push the value in r2 onto the stack
str r2, [sp, -4]
sub sp, sp, 4
@ Different one-liners for Push
str r2, [sp, -4]!
push {r2}
stmdb sp!, {r2}
@ Pop the value from the "top" of the stack into r3
ldr r3, [sp]
add sp, sp, 4
@ One-liners for Pop
ldr r3, [sp], 4
pop {r3}
ldmia sp!, {r2}
<– Push
Pop –>
fact: @ assume input is in r1
push {lr}
cmp r1, #1
beq base_case
@ recursive case
push {r1}
sub r1, #1
bl fact @ get fact(n-1)
pop {r1}
mul r0, r0, r1 @ calc fact(n-1) * n
b continue_code
base_case:
mov r0, #1
continue_code:
pop {lr}
bx lr
<c> |
meaning | flags |
---|---|---|
eq | equal | Z=1 |
ne | not equal | Z=0 |
cs | carry set | C=1 |
cc | carry clear | C=0 |
mi | minus/negative | N=1 |
pl | plus/positive | N=0 |
vs | overflow set | V=1 |
vc | overflow clear | V=0 |
hi | unsigned higher | C=1 ∧ Z=0 |
ls | unsigned lower or same | C=0 ∨ Z=1 |
ge | signed greater or equal | N=V |
lt | signed less | N≠V |
gt | signed greater | Z=0 ∧ N=V |
le | signed less or equal | Z=1 ∨ N≠V |
Which control structures were useful for your assignments?
Is there anything you can do in assembly that goes beyond “typical control structures”?
How do we know how big an array is in memory?
Is it possible to write outside the bounds of the array?
Can you make an array where the size can be changed? (mutable array?)
How do we address a particular element in an array?
ldr r0, =array @ base address
mov r1, 0 @ from_index
mov r2, 7 @ to_index
@ setup
mov r3, 0 @ "accumulator" register
mov r4, 4 @ element size
array_sum:
mul r5, r1, r4 @ calculate offset
ldr r6, [r0, r5] @ load from offset
add r3, r6 @ update accumulator
add r1, 1 @ increment index
cmp r1, r2 @ keep looping?
ble array_sum
What’s the difference between an array and a record?
Imagine you are creating a Point-of-Sale system (cash register) using a microbit. What data structures might be required?
What’s an interrupt? Why are they necessary?
One or multiple lines wired directly to the sequencer.
Interrupts: Enables pre-emptive scheduling, timer driven actions, transient hardware interactions, etc…
BUT: A little bit more work to set up, requires external hardware (“interrupt controller”) to encode external requests.
A “normal function”, called when an interrupt is triggered.
The CPU saves the “caller-save” context on the stack, loads lr
with special value.
Handler saves “callee-save” context, then runs I/O or time-critical code.
Switch out a program (during an interrupt) without it even noticing!
What’s problems can occur when running concurrent programs? What are the possible solutions?
How does the “too much milk” problem help us understand this issue?
When the sequence or timing of threads of execution has an effect on the outcome.
Can result in bugs! (e.g., in Assignment 3!) What is the value at Count
in this code?
What’s mutual exclusion?
Can this be achieved on a microbit?
How would you do it?
How many transmission mediums can you name?
If you were stuck on a desert island what transmission media could you use to send a message for help?
What is a communications protocol?
Why would it be needed?
Explain your answer.
topology is the way that the nodes are connected to one another (both physically and logically)
there are several different ways to connect the nodes together, each with pros and cons
serial | parallel |
---|---|
data is sent one-bit-at-a-time | multiple bits sent simultaneously (e.g. multiple wires) |
fewer bits sent per signal, but simpler | need to keep all the connections in sync |
synchronous | asynchronous |
---|---|
transitions on a clock line | (independent) timers at each end |
no clock skew issues, but requires an extra connection | no extra connections required, but more vulnerable to synchronisation issues |
Why do we need operating systems anyway?
virtual machine | resource manager |
---|---|
provides friendly & safe environment | coordinates access to resources |
memory management | processors |
hardware abstraction | memory |
process management | mass storage |
inter-process comms (IPC) | communications channels |
devices (timers, GPUs, DSPs, peripherals…) |
the kernel is the program (functions, data structures in memory, etc.) which performs the core role(s) of the OS
access to the CPU, memory, peripherals all happens through the kernel through a system call
Why are kernels and (user) programs separate?
How are they different?
Aren’t they both programs?
Are any of these components unneccessary?
What can go wrong in a pipeline?
What are the differences?
Is virtual memory an architecture (hardware) topic or an OS (software) topic?
Finally done. That was epic, thanks for coming with me everybody!