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?
-
Copy/paste a [mcve] of your loop into your question. If you want people to help debug your code, show your exact code. Although one problem is that `str r5, [r0,#0]` doesn't modify r5, so IDK what you mean it's "from" that. Maybe you wanted to `ldr` from an MMIO address into `r5`? – Peter Cordes Aug 03 '20 at 14:26
-
Separately, yes there are tons of example functions you can find in SO answer, and GCC or clang output from compiling simple C functions, e.g. on https://godbolt.org/ (filters directives by default, but you can disable that in the dropdown.) – Peter Cordes Aug 03 '20 at 14:28
-
Assembly language is specific to the assembler, sounds like you are talking about gnu assembler. You dont need the .section text if you dont want, the .thumb_func (before the entry label) is needed and .globl somewhere in the file (or .global) . A bx lr to exit the function. the syntax 1<<16 is not necessarily expected to work, but #0x10000 would, you can send your asm through a C preprocessor but now it becomes yet another assembly langauge. Sounds like you have this all understood and handled. not sure what the issue is. – old_timer Aug 03 '20 at 15:09
-
And you need .thumb somewhere before the code in question otherwise it builds as arm usually (depends on how the tool was configured I assume). Which you should examine in the disassembly as a general check from time to time anyway. Esp with arm/thumb and interwork you want to check the disassembly of hand written asm that is mixed with other code. – old_timer Aug 03 '20 at 15:13
1 Answers
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.
-
Thx.Exactly what I needed.Sorry I didn't post my code.Not at work to get it.I also see you used CMP for 0.TEQ(Test for Equality) would have worked too? – Andrei112 Aug 03 '20 at 17:34
-
I was intentionally not writing the code for you, this is an example with a loop, not real addresse, etc. You can write your code for your task. TST is the appropriate function to determine if a single bit is set or clear (combined with a BNE or BEQ depending). As mentioned in my comment you should have the most success with #0x10000 vs #(1<<16). – old_timer Aug 03 '20 at 18:21
-
TEQ is to test a complete value not a single bit, yes TEQ _might_ be better here (for my example), but TEQ is only supported on armv7-m (cortex-m3,m4,m7) but not on armv6-m (cortex-m0, cortex-m0+) and some of the known armv8-ms (cortex-m23, cortex-m33)(as armv8-m is core dependent not architecture). Depending on how much syntax you use or what you cut and pasted, you might end up generating an instruction the processor doesnt support and end up in a fault which can be difficult to debug. – old_timer Aug 03 '20 at 18:29
-
A number of folks will tell you to use the unified syntax, I wont, I find it harder to get the instruction I want (with gnu at least), and I lean toward all thumb variants, which I tend to just use cpu cortex-m0 to get, but you need to form your own habits and preferences, dont limit yourself to any one opinion/set of preferences. – old_timer Aug 03 '20 at 18:36
-
Thank you a lot.Do you know how I can see the resulting instructions of my assembly? I'm on Atmel Studio 7,but is GCC under the hood.I guess I could search the web for "GCC view instructions compiled". – Andrei112 Aug 04 '20 at 04:34
-
arm-whatever-objdump -d filename,often something like arm-linux-gnueabi-objdump or arm-none-eabi-objdump, etc. I prefer -D and wade through it, if it is only the program itself, .text, then -d. the filename can be the objects if your IDE preserves them otherwise the output elf file if that is preserved. – old_timer Aug 04 '20 at 05:13