asm.md 6.52 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Assembler

## Arithmetic

### Add

```asm
add r0, r1, r2 ; ro = r1 + r2
add r0, r1     ; ro = r0 + r1
add r0, #1     ; ro = r0 + 1, for small constants
```

Set flags while adding

```asm
adds r0, r1, r2 ; ro = r1 + r2, also sets flags
```

### Subtract

```asm
sub r0, r1, r2 ; ro = r1 - r2
```

### Multiply

```asm
mul r0, r1, r2 ; ro = r1 * r2
```

### Divide

```asm
udiv r0, r1, r2 ; ro = r1 / r2, unsigned divide, always rounds down
```

## Logic

### And

```asm
and r0, r1, r2 ; ro = r1 AND r2
```

### OR

```asm
orr r0, r1, r2 ; ro = r1 OR r2
```

### Exclusive or

```asm
eor r0, r1, r2 ; ro = r1 XOR r2
```


## Shift

### Arithmetic shift right

```asm
asr r0, r1, r2 ; ro = r1 >> r2, keeps correct sign!
```

### Logical shift right

```asm
lsr r0, r1, r2 ; ro = r1 >> r2, fills with zeros and doesn't keep correct sign!
```

### Logical shift left

```asm
lsl r0, r1, r2 ; ro = r1 << r2, fills with zeros
```

### Rotate right

```asm
ror r0, r1, r2 ; ro = r1 >> r2, bits will wrap around
```

Aaron Erhardt's avatar
Aaron Erhardt committed
84
85
86
## Load

```asm
Aaron Erhardt's avatar
Aaron Erhardt committed
87
ldr rd, =const    ; load constant
Aaron Erhardt's avatar
Aaron Erhardt committed
88
89
90
91
92
93
94
95
96
97
98
99
100
ldr r1, [r0]      ; load content of address of r0 into r1
ldr r1, [r0, #8]  ; same with offset
ldr r1, [r0], #8  ; post-increment
ldr r1, [r0, #8]! ; pre-increment
```

Load value defined by dcd

```asm
MAX DCD 10
ldr   r3, MAX
```

101
### Store
Aaron Erhardt's avatar
Aaron Erhardt committed
102
103

```asm
104
105
106
107
str r1, [r0]      ; store content of r1 into address of r0 
str r1, [r0, #8]  ; same with offset
str r1, [r0], #8  ; post-increment
str r1, [r0, #8]! ; pre-increment
Aaron Erhardt's avatar
Aaron Erhardt committed
108
109
```

110
## Move
Aaron Erhardt's avatar
Aaron Erhardt committed
111
112

```asm
113
114
mov r0, r1     ; r0 := r1
mov rd, #const ; const max. 16-Bit, otherwise load
Aaron Erhardt's avatar
Aaron Erhardt committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
```

## Compare

```asm
; like subtraction, but only sets flags
cmp r0, r1 ; zero flag set if equal, etc.
cmp r0, 0  ; compare with constant 
```

## Branch

Unconditional branch

```asm
b LABEL ; jump to label
```

Compare binary numbers

```asm
; use "cmp r1 r2" always before branch
; COMMAND ; meaning         C-Code     Flags
beq LABEL ; equal           r1 == r2   Z = 1
bne LABEL ; not equal       r1 != r2   Z = 0
bgt LABEL ; greater         r1 > r2    N = 0
bge LABEL ; greater equal   r1 => r2   N = 0 or Z = 1
blt LABEL ; lower           r1 < r2    N = 1
ble LABEL ; lower equal     r1 =< r2   N = 1 or Z = 1
```

Branch with flag values

```asm
; COMMAND ; meaning           Flags
bcs LABEL ; carry set         C = 1
bcc LABEL ; carry cleared     C = 0
bmi LABEL ; minus             N = 1
bpl LABEL ; plus              N = 0
bvs LABEL ; overflow set      V = 1
bvc LABEL ; overflow cleared  V = 0
beq LABEL ; equal             Z = 1
bne LABEL ; not equal         Z = 0
```

Aaron Erhardt's avatar
Aaron Erhardt committed
160
161
162
## Stack

```asm
Aaron Erhardt's avatar
Aaron Erhardt committed
163
164
push {r1} ; push r1 on the stack
pop  {r1} ; restore r1 from the stack
Aaron Erhardt's avatar
Aaron Erhardt committed
165
166
167
168
169
170

push {r0-r5} ; push r0-r5
pop  {r0-r5} ; pop r0-r5 (in the correct order)

push {lr, r3, r10-12} ; push lr, r3 and r10-r12
pop  {lr, r3, r10-12} ; pop lr, r3 and r10-r12
Aaron Erhardt's avatar
Aaron Erhardt committed
171
172
```

173
## Subroutines
Aaron Erhardt's avatar
Aaron Erhardt committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

```asm
main
    bl label ; run subroutine

label
    ; push all registers the subroutine changes except returned registers
    push {lr, ...} 
    ; ...         ; other code
    pop {lr, ...} ; pop the registers again
    bx lr         ; jump back
```

## Pass parameters

### Register

```asm
main
    ldr r0, =1 ; initialize parameters
    ldr r1, =2
    bl add_nums ; run subroutine
	; r2 can now be used as returned value

add_nums
    push {lr}
    add r2, r0, r1 ; add r0 and r1 and return value at r2
    pop {lr}
    bx lr
```

### Stack

```asm
main
	ldr r7, =1 ; initialize parameters
	ldr r8, =2

	; prepare parameters and return values
    push {r7} ; parameter 1
    push {r8} ; parameter 2
    push {r9} ; return value 1

    bl add_nums ; run subroutine

    pop {r9} ; get return value from the stack
    pop {r8} ; free stack space again
    pop {r7} ; free stack space again

add_nums
    push {lr, r0-r2} ; increments stack pointer by 4 * (amount of registers)!

     ; load parameters into registers
    ldr r0, [sp, #4*6] ; 4*4 + 4*2 -> r7 (was pushed first, highest address)
    ldr r1, [sp, #4*5] ; 4*4 + 4*1 -> r8

    add r2, r0, r1 ; perform actual calculation

    ; store return values on reserved the stack space
    str r2, [sp, #4*4] ; 4*4 + 4*0 -> r9

    pop {lr, r0-r2}
    bx lr
```
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326


# IO

IO is memory mapped, it is read and set just like a block of memory.

## Typical register types

+ Control register (set behavior)
+ Status register
+ Data register

## STM32

### RCC (Reset and Control Logic)

Used to explicitly turn on other I/O blocks by setting bits in the registers.

### GPIO (General Purpose I/O)

Configuration: 

+ Set RCC bits to enable I/O block
+ Set pins as input, output, alternate function (reserve pin for other I/O blocks) or analog with two bits in the MODER register
+ Adjust edge steepness (Flankensteilheit) with two bits in the OSPEEDR register
+ Set pull up resistance to NONE, UP or DOWN with two bits in the PUPDR register

Output: Set bits of the ODR register to activate individual pins
 
Input: Read bits of the IDR register to get values of individual pin

**Example**

```asm
; define port addresses and register offsets (data sheet)...

InitOutputPortB
    push {r0, r3, r4, lr}

    ; Enable I/O block for PortB
    ldr r3, = RCC          ; Load start address of RCC registers into r3
    ldr r0, [r3, #AHB1ENR] ; Load current register values
    orr r0, r0, #IOPBEN    ; Use logical OR to enable the bit for GPIOBEN and leave the rest unchanged
    str r0, [r3, #AHB1ENR] ; Store value into the register to enable I/O on PortB

    ; Configure PortB
    ldr r3, = GPIOB        ; Load start address of GPIOB registers into r3
    ldr r0, = 0x00005555   ; Load values for configuring the MODER register, using 0x5 = 01_01 to set all pins as output
    str r0, [r3, #MODER]   ; Store value into the register to enable configuration

    ; Turn on LEDs
    ldr r0, #3             ; Set first to bits
    str r0, [r3, #ODR]     ; Load value into ODR register to enable the first to outputs (LEDs)

    pop {r0, r3, r4, lr}
```


### Systick timer

Counts down from a start value until it reaches zero. Then is sets a flag, invokes an interrupt, resets the start value and counts down again.

STK_CTRL register:

+ COUNTFLAG: counter has reached zero
+ CLKSOURCE: select counter clock
+ TICKINT: enable interrupt
+ ENABLE: enable counter

STK_LOAD register: 24 bit reset value

STK_VAL register: current counter value


### Capture/Compare-Timer

CR1 register: configure timer

CNT register: counter value

ARR register: reset value

PSC register: pre-scale value, divide clock frequency

CCR1-CCR4 registers: 

+ compare with counter value and set output pin if counter surpasses the control value
+ on input (e. g. rising edge) capture the current counter value