-2

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?

Andrei112
  • 3
  • 1
  • 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 Answers1

0

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.

halfer
  • 19,824
  • 17
  • 99
  • 186
old_timer
  • 69,149
  • 8
  • 89
  • 168
  • 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