Simple Model of a Microprocessor System
A Processing Unit which
performs operations on data
Memory, which stores:
Other peripheral devices
e.g. displays, USB ports,
network devices,
keyboards, mice, ...
Memory
Programs (instructions)
Data
BUS
Data: representing text, images,
videos, sensor readings, ,
audio, etc. ...
Instructions: Programs are
composed of sequences of
instructions that control the
actions of the processing unit
3D1 / Microprocessor Systems I
Memory
Processing Unit
e.g. ARM7TDMI
+ - = ? &
1
Program 7.1 Upper Case String
Design and write an assembly
language program to convert a
string stored in memory to UPPER
CASE
String sequence of ASCII
characters stored in consecutive
memory locations
3D1 / Microprocessor Systems I
Memory
8 bits
1 byte
0xA1000040
0xA1000041
0xA1000042
0xA1000043
0xA1000044
0xA1000045
0xA1000046
0xA1000047
0xA1000048
0xA1000049
0xA100004A
char = first character in string
0xA100004B
0xA100004C
while (char not past end of string)
{
if (char a AND char z)
{
char = char AND 0xFFFFFFDF
}
char = next character
}
0xA100004D
0xA100004E
0xA100004F
0xA1000050
??
??
??
??
h
e
l
l
o
??
??
??
??
??
??
??
??
Memory
2
3D1 / Microprocessor Systems I
Memory
Load Store Architecture
ARM7TDMI is based on a
Load Store Architecture
Cannot directly perform
operations (e.g. addition,
subtraction, comparison, ... )
on values in memory
Only way to operate on a
value stored in memory is to
load it into a register, then
operate on the register
Only way to change a value
in memory is to store the
value from a register into
memory
RISC
CISC
(e.g. ARM)
(e.g. x86)
Simple
operations
Complex
operations
Small / simple
design
Large / complex
Design
More operations
per unit time
Fewer operations
per unit time
Trade-off
3D1 / Microprocessor Systems I
Memory
Program 7.1 Upper Case String
Refine pseudo-code solution
char = first character in string
while (char not past end of string)
{
if (char a AND char z)
{
char = char AND 0xFFFFFFDF
}
address = address of first character
char = Memory.byte [address]
while (char not past end of string)
{
if (char a AND char z)
{
char = char AND 0xFFFFFFDF
Memory.byte[address] = char
}
char = next character
address = address + 1
char = Memory.byte[address]
}
}
Program 7.1 Upper Case String
How do we know when we have
reached the end of the string?
NULL terminated strings use the
value 0 (ASCII NULL character
code) to denote the end of a string
3D1 / Microprocessor Systems I
Memory
8 bits
1 byte
0xA1000040
0xA1000041
0xA1000042
0xA1000043
0xA1000044
0xA1000045
0xA1000046
0xA1000047
address = address of first character
char = Memory.byte [address]
0xA1000048
0xA1000049
0xA100004A
while (char 0)
{
if (char a AND char z)
{
char = char AND 0xFFFFFFDF
Memory.byte[address] = char
}
address = address + 1
char = Memory.byte[address]
}
0xA100004B
0xA100004C
0xA100004D
0xA100004E
0xA100004F
0xA1000050
??
??
??
??
h
e
l
l
o
00
??
??
??
??
??
??
??
Memory
5
Load / Store Instructions
3D1 / Microprocessor Systems I
Memory
Load Rd = Memory.<size>[<address>]
Load a word-, half-word- or byte- <size> value ...
... from Memory at a specified <address> ...
... into a register
LDR Rd, <address>
load word
LDRH Rd, <address>
load half-word
LDRB Rd, <address>
load byte
Store Memory.<size>[<address>] = Rd
Store a a word-, half-word- or byte- <size> value ...
... from a register ...
... into Memory at a specified <address>
STR Rd, <address>
store word
STRH Rd, <address>
store half-word
STRB Rd, <address>
store byte
Addressing Mode [Rn, #0] or [Rn]
3D1 / Microprocessor Systems I
Memory
Addressing mode method of specifying the <address>
to be used in a load / store operation
Address used is called the effective address
Immediate Offset (with a default zero offset)
Rn is the base register
<address> = Rn
Example: load word-size value from memory at address
0xA1000000 into register r1
r1 = Memory.word[0xA1000000]
LDR
LDR
r0, =0xA1000000 ; Initialise base register r0 = 0xA1000000
r1, [r0]
; r1 = Memory.word[r0]
7
Addressing Mode [Rn, #0] or [Rn]
3D1 / Microprocessor Systems I
Memory
Example: Store word-size value from register R1 into
memory at address 0xA1000000
Memory[0xA1000000] = r1
LDR
STR
r0, =0xA1000000 ; Initialise base register r0 = 0xA1000000
r1, [r0]
; Memory.word[r0] = r1
Example: Load byte-size value from register r1 into
memory at address 0xA1000000
r1 = Memory.byte[0xA1000000]
LDR
LDRB
r0, =0xA1000000 ; Initialise base register r0 = 0xA1000000
r1, [r0]
; r1 = Memory.byte[r0]
Program 7.1a Upper Case String
3D1 / Microprocessor Systems I
Memory
start
LDR
wh1
ADD
LDRB
CMP
BNE
; while ( (char = Memory.byte[address])
testwh1
;
!= 0 ) {
r0, #'a'
; if (char >= 'a'
endif1
;
AND
r0, #'z'
;
char <= 'z')
endif1
; {
r0, #0x00000020 ;
char = char AND NOT 0x00000020
r0, [r1]
;
Memory.byte[address] = char
; }
r1, r1, #1
; address = address + 1
r0, [r1]
; }
r0, #0
;
wh1
;
stop
B
CMP
BCC
CMP
BHI
BIC
STRB
endif1
testwh1
stop
r1, =0xA1000000 ; address = 0xA1000000
while construct evaluates condition at end of loop with
an initial branch to the evaluation more efficient
Use Vision to initialise memory with a test string
Indirect Addressing
3D1 / Microprocessor Systems I
Memory
Storing an address in a register and subsequently using
the register as an operand in a load/store operation is
an example of indirection
Indirection is an important concept in Computing
generally, not just assembly language programming
LDR
LDRB
r0, =0xA1000000 ; Initialise base register r1 = 0xA1000000
r1, [r0]
; r1 = Memory.byte[r0]
We can say r0 points to the data in memory at
address 0xA1000000
In some contexts (e.g. high-level programming
languages such as C or C++) r0 could be referred to as a
pointer to some data
10
3D1 / Microprocessor Systems I
Memory
Endianness
Little-endian byte ordering least-significant byte of
word or half-word stored at lower address in memory
Big-endian byte ordering most-significant byte of
word or half-word stored at lower address in memory
8 bits
1 byte
0xA10000D6
0xA10000D7
0xA10000D8
0xA10000D9
0xA10000DA
0xA10000DB
0xA10000DC
02
03
04
Big-endian
05
0xA10000DD
00
01
02
03
04
05
06
07
Memory
05
04
03
02
Little-endian
11
3D1 / Microprocessor Systems I
Memory
Load / Store Bytes, Half-words and Words
??
??
32
04
85
EB
??
??
0xA1000042
0xA1000043
0xA1000044
Byte, half-word, word
at address 0xA1000044
0xA1000045
0xA1000046
0xA1000047
0xA1000048
0xA1000049
LDR r0, =0xA1000044
LDRB r1, [r0]
00
00
00
31
LDR r0, =0xA1000044
LDRH r1, [r0]
00
31
LDR
LDR
r0, =0xA1000044
r1, [r0]
EB
31
32
8 7
00
04
32
16 15
85
04
32
0
12
3D1 / Microprocessor Systems I
Memory
Loading Signed Bytes and Half-words
Sign extension performed when loading signed bytes or
half-words to facilitate correct subsequent 32-bit
signed arithmetic
LDR
LDRSB
r0, =0xA1000044
r1, [r0]
00
00
00
31
32
8 7
0
0xA1000042
LDR
r0, =0xA1000044
LDRSH r1, [r0]
0xA1000043
00
31
00
04
32
16 15
0xA1000044
0xA1000045
0xA1000046
0xA1000047
0xA1000048
LDR
LDRSB
r0, =0xA1000046
r1, [r0]
FF
FF
FF
31
LDR
r0, =0xA1000046
LDRSH r1, [r0]
FF
31
8 7
FF
EB
16 15
0xA1000049
85
??
??
32
04
85
EB
??
??
Remember:
interpretation!!
85
0
13
DCD, DCW and DCB Assembler Directives
3D1 / Microprocessor Systems I
Memory
Use the assembler to initialise contents of memory
Example: instead of manually writing a test string into
memory, the string can be included with program
machine code by the assembler
AREA
IMPORT
EXPORT
UpperCaseString, CODE, READONLY
main
start
LDR
r1, =teststr
start
...
...
<rest of program>
...
...
teststr
AREA
DCB
; address = 0xA1000000
...
...
TestData, DATA, READWRITE
"hello",0
; NULL terminated test string
END
14
DCD, DCW and DCB Assembler Directives
3D1 / Microprocessor Systems I
Memory
DCD, DCW and DCB are assembler directives. They are
not instructions and no machine code is produced.
Other data declaration examples
8 word values
mywords
DCD
DCD
0x4D1F4004, 0x10301030, 0x141030D4, 0xE4503003
0x4AB345F0, 0x3049FDEA, 0x0400D4F8, 0x34FD303A
Lotto numbers as byte values
draw
bonus
DCB
DCB
32, 43, 10, 11, 14, 15
7
2 half-word values
values
DCW
407, -208
15
Other Assembler Directive
3D1 / Microprocessor Systems I
Memory
AREA directive
Marks the beginning of a section and specifies attributes for
the section
Sections are indivisible sequences of instructions and/or data
Attribute examples: CODE, READONLY, DATA, READWRITE
Attributes define how a section is loaded into memory
Programs must contain at least one CODE section
END directive
Tells the assembler to stop processing the source file
IMPORT / EXPORT directives
EXPORT directive exports labels for use by other assemblies
IMPORT directive allows one assembly to use a label
exported by another assembly
16
Alignment
3D1 / Microprocessor Systems I
Memory
ARM7TDMI expects all memory accesses to be aligned
Examples
Word-aligned
0x00000000, 0x00001008, 0xA100000C
Not word-aligned
0x00000001, 0x00001006, 0xA100000F
Half-word aligned
0x0000000, 0x00001002, 0xA100000A
Not half-word aligned
0x00000003, 0x00001001, 0xA100000B
See ARM Architecture Reference Manual Section A2.8
Unaligned accesses are permitted but the result is
unlikely to be what was intended
Unaligned accesses are supported by later ARM
architecture versions
17
3D1 / Microprocessor Systems I
Memory
Unaligned Access Example
Load word at address 0xA10000DB
0xA10000DB
1 0
1 0 1 1 0 1 1
31 30
8 bits
1 byte
00
01
02
03
04
05
06
07
08
09
10
0xA10000D6
0xA10000D7
0xA10000D8
0xA10000D9
address is rounded down to nearest
aligned address
0xA10000DA
0xA10000DB
0xA10000DC
0xA10000DD
0xA10000DE
0xA10000D8
1 0
1 0 1 1 0 0 0
31 30
0xA10000DF
0xA10000E0
Memory
loaded value is rotated right 3 bytes
before being stored in destination register
05
04
03
02
04
03
02
05
18
Addressing Mode [Rn], #+/-<offset>
3D1 / Microprocessor Systems I
Memory
Immediate post-indexed
<address> = Rn
Rn = Rn +/- <12-bit offset>
After calculating the effective address, the immediate value
<offset> is added/subtracted to/from the base register Rn
Convenient way of updating base register to point to address
of next value in memory
Example: load three consecutive half-word values,
beginning at address 0xA1001000, into registers r0, r1
and r2
LDR
LDRH
LDRH
LDRH
r0,
r1,
r2,
r3,
=0xA1001000
[r0], #2
[r0], #2
[r0], #2
;
;
;
;
Initialise base register r1 = 0xA1001000
r1 = Memory.halfword[r0], r0 = r0 + 2
r2 = Memory.halfword[r0], r0 = r0 + 2
r3 = Memory.halfword[r0], r0 = r0 + 2
19
Program 7.1b Upper Case String
start
AREA
IMPORT
EXPORT
UpperCaseString, CODE, READONLY
main
start
LDR
r1, =teststr
3D1 / Microprocessor Systems I
Memory
LDRB
CMP
BNE
; address = 0xA1000000
; while ( (char = Memory.byte[address])
testwh1
;
!= 0 ) {
r0, #'a'
; if (char >= 'a'
endif1
;
AND
r0, #'z'
;
char <= 'z')
endif1
; {
r0, #0x00000020 ;
char = char AND NOT 0x00000020
r2, r1, #1
;
store_address = address - 1
r0, [r2]
;
Memory.byte[store_addres] = char
; }
r0, [r1], #1
; }
r0, #0
;
wh1
;
stop
stop
teststr
AREA
DCB
TestData, DATA, READWRITE
"hello",0
; NULL terminated test string
wh1
endif1
testwh1
B
CMP
BCC
CMP
BHI
BIC
SUB
STRB
END
20
Addressing Mode [Rn, #+/-<offset>]
3D1 / Microprocessor Systems I
Memory
Immediate Offset (with non-zero offset)
<address> = Rn +/- <12-bit offset>
Effective address is calculated by adding <offset> to the value
in the base register Rn
Base register Rn is not changed
Example: load three consecutive word-size values,
beginning at address 0xA1001000, into registers r1, r2
and r3
LDR
LDR
LDR
LDR
r0,
r1,
r2,
r3,
=0xA1001000
[r0]
[r0, #4]
[r0, #8]
;
;
;
;
Initialise base register r1 = 0xA1001000
r1 = Memory.word[r0 + 0] (default = 0)
r2 = Memory.word[r0 + 4]
r3 = Memory.word[r0 + 8]
21
Program 7.1c Upper Case String
start
AREA
IMPORT
EXPORT
UpperCaseString, CODE, READONLY
main
start
LDR
r1, =teststr
3D1 / Microprocessor Systems I
Memory
LDRB
CMP
BNE
; address = teststr
; while ( (char = Memory.byte[address])
testwh1
;
!= 0 ) {
r0, #'a'
; if (char >= 'a'
endif1
;
AND
r0, #'z'
;
char <= 'z')
endif1
; {
r0, #0x00000020 ;
char = char AND NOT 0x00000020
r0, [r1, #-1]
;
Memory.byte[addres - 1] = char
; }
r0, [r1], #1
; }
r0, #0
;
wh1
;
stop
stop
teststr
AREA
DCB
TestData, DATA, READWRITE
"hello",0
; NULL terminated test string
wh1
endif1
testwh1
B
CMP
BCC
CMP
BHI
BIC
STRB
END
22
Addressing Mode [Rn, +/-Rm]
3D1 / Microprocessor Systems I
Memory
Register offset
<address> = Rn +/- Rm
Effective address is calculated by adding offset register Rm to
base register Rn
Rn and Rm are not changed
Example: load three consecutive half-word values,
beginning at address 0xA1001000, into registers r1, r2
and r3
LDR
LDR
LDRH
ADD
LDRH
ADD
LDRH
r0,
r4,
r1,
r4,
r2,
r4,
r3,
=0xA1001000
=0
[r0, r4]
r4, #2
[r0, r4]
r4, #2
[r0, r4]
;
;
;
;
;
;
;
Initialise base register r1 = 0xA1000000
Initialise offset register r4 = 0
r1 = Memory.halfword[r0 + r4]
r4 = r4 + 2
r2 = Memory.halfword[r0 + r4]
r4 = r4 + 2
r3 = Memory.halfword[r0 + r4]
23
Program 7.1d Upper Case String
AREA
IMPORT
EXPORT
UpperCaseString, CODE, READONLY
main
start
LDR
LDR
r1, =teststr
r2, =0
3D1 / Microprocessor Systems I
Memory
start
wh1
ADD
LDRB
CMP
BNE
; while ( (char = Memory.byte[address
testwh1
;
+ offset]) != 0 ) {
r0, #'a'
; if (char >= 'a'
endif1
;
AND
r0, #'z'
;
char <= 'z')
endif1
; {
r0, #0x00000020 ;
char = char AND NOT 0x00000020
r0, [r1, r2]
;
Memory.byte[address + offset] = char
; }
r2, r2, #1
; offset = offset + 1
r0, [r1, r2]
; }
r0, #0
;
wh1
;
stop
B
CMP
BCC
CMP
BHI
BIC
STRB
endif1
testwh1
stop
; address = teststr
; offset = 0
24
Program 7.2a Sum
3D1 / Microprocessor Systems I
Memory
Design and write an assembly language program that
will calculate the sum of 100 word-size values stored in
memory
sum = 0
do
{
Option 1
Use offset for
loop condition
sum = sum + Memory.word[address + offset]
offset = offset + 4
} while (offset < 400)
sum = 0
count = 100
do
{
Option 2
Use separate
counter for
loop condition
sum = sum + Memory.word[address + offset]
offset = offset + 4
count = count - 1
} while (count > 0)
25
3D1 / Microprocessor Systems I
Memory
Program 7.2a Sum
AREA
IMPORT
EXPORT
Sum, CODE, READONLY
main
start
EQU
100
MOV
LDR
MOV
LDR
R0,
R1,
R2,
R3,
#0
=nums
#0
=MAX
do1
LDR
ADD
ADD
SUBS
BCS
R4,
R0,
R2,
R3,
do1
[R1, R2]
R0, R4
R2, #4
R3, #1
stop
stop
nums
AREA
DCD
...
TestData, DATA, READWRITE
1,1,1,1,1,1,1,1,1,1
...
MAX
start
;
;
;
;
;
;
;
;
;
;
sum = 0
address = nums
offset = 0
count = MAX
do {
tmp = Memory.word[address + offset]
sum = sum + tmp
offset = offset + 4
count = count - 1
} while (count > 0)
END
26
Addressing Mode [Rn, +/-Rm, shift #count]
3D1 / Microprocessor Systems I
Memory
Scaled register offset
<address> = Rn +/- Rm shift count
Effective address is calculated by adding (offset register Rm
shifted by count bits) to base register Rn
Shift operation can be LSL, LSR, ASR, ROR, RRX
Rn and Rm are not changed
Example: load three consecutive word values,
beginning at address 0xA1001000, into registers r1, r2
and r3
LDR
LDR
LDR
ADD
LDR
ADD
LDR
r0,
r4,
r1,
r4,
r2,
r4,
r3,
=0xA1001000 ; Initialise base register r1 = 0xA1000000
=0
; Initialise offset register r4 = 0
[r0, r4, LSL #2] ; r1 = Memory.word[r0 + (r4 * 4)]
r4, #1
; r4 = r4 + 1
[r0, r4, LSL #2] ; r2 = Memory.word[r0 + (r4 * 4)]
r4, #1
; r4 = r4 + 1
[r0, r4, LSL #2] ; r3 = Memory.word[r0 + (r4 * 4)]
27
3D1 / Microprocessor Systems I
Memory
Program 7.2b Sum
MAX
AREA
IMPORT
EXPORT
Sum, CODE, READONLY
main
start
EQU
100
MOV
LDR
MOV
R0, #0
R1, =nums
R2, #0
LDR
R3, [R1, R2, LSL #2] ;
ADD
ADD
CMP
BCC
R0, R0, R3
R2, R2, #1
R2, #MAX
do1
stop
...
...
start
do1
stop
;
;
;
;
sum = 0
address = nums
offset = 0
do {
tmp = Memory.word[address
+ offset * 4]
; sum = sum + tmp
; offset = offset + 1
; } while (offset < MAX)
;
END
28
3D1 / Microprocessor Systems I
Memory
Summary of LDR/STR Addressing Modes
Addressing mode
Syntax
W, B
H, SH, SB Operation
Immediate Offset
[<Rn>, #+/-<offset>]
address Rn +/- offset
Register Offset
[<Rn>, +/-<Rm>]
address Rn +/- Rm
Scaled Register Offset
[<Rn, +/-<Rm>, <shift> #<count>]
Immediate Pre-Indexed
[<Rn>, #+/-<offset>]!
Rn Rn +/- offset
address Rn
Register Pre-Indexed
[<Rn>, +/-<Rm>]!
Rn Rn +/- Rm
address Rn
Scaled Register Pre-Indexed
[<Rn, +/-<Rm>, <shift> #<count>]!
Immediate Post-Indexed
[<Rn>], #+/-<offset>
address Rn
Rn Rn +/- offset
Register Post-Indexed
[<Rn>], +/-<Rm>
address Rn
Rn Rn +/- Rm
Scaled Register Post-Indexed
[<Rn], +/-<Rm>, <shift> #<count>
address Rn +/- (Rm <shift> <count>)
Rn Rn +/- (Rm <shift> <count>)
address Rn
address Rn
Rn Rn +/- (Rm <shift> <count>)
All modes are available for loads/stored of words and
unsigned bytes
A subset of the modes are available for loads/stores of
unsigned half-words, signed half-words and signed bytes
Note 12-bit offsets for W, B and 8-bit offsets for H, SH & SB
29
Program 7.3 ASCII string to value
3D1 / Microprocessor Systems I
Memory
Design and write an assembly language program that
will convert an ASCII representation of a hexadecimal
value to a value. The string should be stored as a NULLterminated string in memory and the converted value
should be stored in register r0.
30
Program 7.4 Value to ASCII String
3D1 / Microprocessor Systems I
Memory
Design and write an assembly language program to
convert a word-size unsigned value stored in memory
to its hexadecimal ASCII string representation.
31
Program 7.5 Cardinality
3D1 / Microprocessor Systems I
Memory
Design and write a program that will determine the
cardinality of a set of word values stored in memory.
The result (cardinality) should be stored in r0.
e.g. if the values stored in memory are ...
4, 9, 3, 4, 7, 9, 12, 10, 4, 7, 3, 12, 5, 5, 7
then the program should store 7 in r0
32