Introduction To Assembler: Microcontroller VL Thomas Nowak TU Wien
Introduction To Assembler: Microcontroller VL Thomas Nowak TU Wien
Microcontroller VL
Thomas Nowak
TU Wien
1
Overview
● Introduction
● Simple Processor Architecture
● Addressing Modes
● Instructions
● Examples
● Guidelines
● Summary
2
Introduction
● Why should I learn assembler?
– to see how all programs you write “really”
end up
– to understand the CPU architecture better
– to see where speed improvements are
possible
– to realize there is no big secret behind it all
– to pass the course ;)
3
Introduction
● Assembler is basically a 1-1 mapping to
machine code (with a few twists)
● Assembly language is human readable
– machine code is not
● No high-level language constructs, e.g. if,
while, ...
– how to reassemble these constructs: later in
this presentation (Examples)
● No nested expressions
– e.g. you cannot write add (mult 3,2), 1 4
Introduction
● Operate directly on processor registers
– no local variables
● Memory access is not transparent
– different instructions for different locations
● No standardized instruction set
– different instruction sets on different
computer architectures
– highly hardware dependent
5
Simple Processor Architecture
● n General Purpose Registers (GPRs)
● Program Counter (PC)
– stores address of current instruction
● Stack Pointer (SP)
– points to top of stack (TOS)
– both possible: TOS or TOS+1 stored in SP
● Status Word (SW)
– stores status of last instruction
6
Simple Processor Architecture
7
Addressing Modes
● code addressing (for jump instructions)
– absolute
– relative
– indirect
● data addressing (for memory access)
– direct
– indirect (register/memory)
– autoincrement/-decrement
– etc.
8
Addressing Modes
● code addressing
– you can define labels to code addresses
– “jmp label3” instead of “jmp 0x04F3”
● direct addressing
– effective address is the given address
– “ld r1, 0x4FF3” loads the content of 0x4FF3
into register r1
● indirect addressing
– effective address is the content of the given
register/memory location 9
Addressing Modes
● autoincrement
– indirect addressing mode that alters the
indirecting register/memory location
– “ld r1, r5+” loads contents of r5's value into
r1 and increments r5
● addresses are often written as
offset(base), i.e. address = base + offset
– “ld r1, -8(r5)” loads contents of memory
location ((r5's value) – 8) into register r1
10
Instructions
● Three styles of binary operators
– OP src1, src2, dst
i.e. dst := src1 OP src2
– OP r1, r2
i.e. r1 := r1 OP r2
– OP r1 (other operand in AC register)
● Two styles of comparing registers
– CMP r1, r2, dst
i.e. dst := r1 CMP r2
– having the status word updated after certain
11
operations (e.g. negative and zero bit)
Instructions
● Arithmetic/logical instructions
– ADD, SUB, AND, NOT, ...
– different instructions for integer and float
registers
● Jump instructions
– conditional (e.g. BREQ) and unconditional
(BR) branches
– jump to subroutine (JSR) saves the current
program count (PC) to a register or stack (RA)
– RET jumps to address in RA
12
Instructions
● Load/store instructions
– LD, ST
– many addressing modes possible (CISC CPUs)
– transparent stack instructions possible
(PUSH, POP)
– LDI r1, value (Load Immediate) assigns value
to register r1
● Move instruction (MOV)
– MOV r1, r2 copies r2's value to r1
13
Instructions
● Compare instructions
– combined compare/branch instructions
possible
Example: branch if r1's value is greater than
r2's (BRGT r1, r2, label)
14
Examples
● Implementing an if-statement in
Assembler 1/2
if(r1==2)
r2=0;
else
r2=1;
15
Examples
● Implementing an if-statement in
Assembler 2/2
ldi r3, 2 r3 := 2;
cmp r1, r3 r1 – r3; //update SW
brne else if(!zero_flag) goto else;
ldi r2, 0 r2 := 0;
jmp end goto end;
else: else:
ldi r2, 1 r2 := 1;
end: end: 16
Examples
● Implementing a while-loop in Assembler
1/2
● r1 is a CPU register
17
Examples
● Implementing a while-loop in Assembler
2/2
while:
while:
cmpi r1, 20 r1 – 20; //update SW
brge end if(!negative_flag) goto
addi r1, 1 end;
jmp while r1++;
end: goto while;
end:
18
Examples
● Implementing a do-while-loop in
Assembler 1/2
do
--r1;
while(r1 > 5);
● r1 is a CPU register
19
Examples
● Implementing a do-while-loop in
Assembler 2/2
ldi r2, 5 r2 := 5;
do: do:
addi r1, (-1) r1--;
cmp r2, r1 r2 – r1; //update SW
brlt do if(negative_flag) goto
do;
20
Guidelines
● Look how the compiler transforms a high-
level language program to assembler
code
– gcc -S code.c creates assembler code file
code.s
– this is a good source of negative examples
– gcc allocates every variable on the stack, this
is often not necessary
21
Guidelines
● Name used registers
– use the .equ directive to create aliases for
register numbers
– if you use a register for different purposes in
different parts of your program, give it
multiple names
22
Guidelines
● Debug systematically
– it is nearly impossible to code assembler
“blindly”, i.e. without continuous testing
– debug only small code blocks simultaneously
– use LEDs to display current state while
debugging
23
Guidelines
● Be redundant (sometimes)
– assembler code is susceptible to hard-to-see
mistakes
– e.g. create redundant labels just to clarify the
control flow:
cpi r1, 1
breq equals_one
not_equals_one:
...
equals_one:
...
– label not_equals_one is redundant here, but
documents the control flow 24
Summary
● Assembler is a 1-1 mapping to machine
code
● Machine dependent instruction set
● Addressing
– code
– data
– direct, indirect modes
25
Summary
● Groups of assembler commands
– arithmetic/logical
– jumps
– load, store
– compare
– move
26