I need to craft an ASM function. I got the most of it done,but I don't manage to get it to work as it should. I want to do a loop that runs to infinity untill a bit in a certain register(SysTick->CTRL Flag) becomes set. I used TST r5,#Val. The val is 1<<16 written as hex Then I do a BNE to loop label. It just exits the loop. r5 is from STR r5,[r0,#0] Where r0 has the SysTick CTRL address. Has anyone some complete ASM function examples. I used .global funcname I used .segment text I used .thumb_func Any other stuff to worry about?
First off, assembly language is specific to the assembler.
For gnu:
.thumb
.globl myfun
.thumb_func
myfun:
ldr r0,=0x12345678
myfun_inner:
ldr r1,[r0]
cmp r1,#0
bne my_fun_inner
bx lr
so.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <myfun>:
0: 4802 ldr r0, [pc, #8] ; (c <myfun_inner+0xa>)
00000002 <myfun_inner>:
2: 6801 ldr r1, [r0, #0]
4: 2900 cmp r1, #0
6: d1fe bne.n 0 <my_fun_inner>
8: 4770 bx lr
a: 0000 .short 0x0000
c: 12345678 .word 0x12345678
gnu has an interesting strange label shortcut that I don't particularly like but some do:
.thumb
.globl myfun
.thumb_func
myfun:
ldr r0,=0x12345678
1:
ldr r1,[r0]
cmp r1,#0
bne 1b
bx lr
Think of the 1b as 1 backward, you can have several 1:, 2: etc labels in this code and 1b or 1f will reference the nearest 1: forward or backward. and produces the same code:
6: d1fe bne.n 0 <my_fun_inner>
This is a relative jump so even though I have disassembled the object, when you link and disassemble the linked binary, that will be the same machine code:
ldr r0,=0x12345678
Is pseudo code supported by some ARM assemblers. Gas in particular will attempt to find the optimized solution:
.thumb
ldr r0,=0x12345678
ldr r0,=1
ldr r0,=0x20002
00000000 <.text>:
0: 4802 ldr r0, [pc, #8] ; (c <.text+0xc>)
2: f04f 0001 mov.w r0, #1
6: f04f 1002 mov.w r0, #131074 ; 0x20002
a: 0000 .short 0x0000
c: 12345678 .word 0x12345678
Now that was a little dangerous because it chose a thumb2 instruction, so you may wish to be ultra generic for cortex-ms (thus far, actual armv8m chips thus far)
.cpu cortex-m0
.thumb
ldr r0,=0x12345678
ldr r0,=1
ldr r0,=0x20002
00000000 <.text>:
0: 4801 ldr r0, [pc, #4] ; (8 <.text+0x8>)
2: 4802 ldr r0, [pc, #8] ; (c <.text+0xc>)
4: 4802 ldr r0, [pc, #8] ; (10 <.text+0x10>)
6: 0000 .short 0x0000
8: 12345678 .word 0x12345678
c: 00000001 .word 0x00000001
10: 00020002 .word 0x00020002
The .short in there is an alignment spacing thing in place to keep the words word aligned. this is a cutting edge version of binutils you sometimes/often see a nop placed in there to fill space. So now perhaps the tool is filling with zeros.
Minimal complete would be along the lines of
.cpu cortex-m0
.thumb
.globl myfun
.thumb_func
myfun:
ldr r0,=0x12345678
myfun_inner:
ldr r1,[r0]
cmp r1,#0
bne my_fun_inner
bx lr
And if you examine the output of gcc then you will see something closer to maximal, with a lot more syntax. So aim for somewhere in between for your personal preference. I often don't use the .cpu unless I need to as it used to default to armv4t, which is pretty much "all thumb variants" but clearly now it doesn't, so I will have to change my habits. Here again, always check your output of asm code, especially in this arm arm/thumb multiple thumb2 extensions, multiple instruction sets with the same tool.