Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ARM Assembly Local Labels

Tags:

gcc

assembly

arm

I'm currently reading a tutorial on Raspberry Pi OS development and was wondering about the way local labels are used in this code snippet (GCC ARM Assembly):

    ...
    b       2f
1:
    stmia   r4!, {r5-r8}
2:
    cmp     r4, r9
    blo     1b
    ...

If you use 1: as a label you have to specify either f or b after the jump instruction to make the assembler know in which direction the jump is aimed. As far as I know you could also use this:

    ...
    b       .2
.1:
    stmia   r4!, {r5-r8}
.2:
    cmp     r4, r9
    blo     .1
    ...

I think this option is a lot less confusing (local labels are also marked with a dot in x86 assembly), because there is no additional letter after the label reference. I have tested the resulting machine code and it's the same. So my questions:

  • Why would you use the one variant over the other?

  • Why is it necessary to specify the direction of the jump with either f or b?

like image 899
qwertz Avatar asked Sep 01 '15 21:09

qwertz


People also ask

What is a label in ARM assembly?

A label is a symbol that represents the memory address of an instruction or data. The address can be PC-relative, register-relative, or absolute. Labels are local to the source file unless you make them global using the EXPORT directive. The address given by a label is calculated during assembly.

Why are labels used in assembly code?

A "LABEL" is something so that you don't have to manually work out the addresses to jump to. It is not an instruction and takes up no space (excepting as the assembler might align code to make it valid).

What is data label in assembly language?

A data label identifies the location of a variable, providing a convenient way to reference the variable in code. The following, for example, defines a variable named count: count DWORD 100. The assembler assigns a numeric address to each label.


2 Answers

The important difference is that the numbered local labels can be reused without worry and that is why you need to specify the direction too. You can jump to preceding or following one, but not the ones beyond them.

1: foo
...
1: bar
...
jmp 1b # jumps to bar
...
jmp 1f # jumps to baz
...
1: baz
...
1: qux
...
jmp 1b # jumps to qux

As long as you only use them within a single block only, you can be sure they will work as intended and not conflict with anything else.

like image 177
Jester Avatar answered Nov 20 '22 17:11

Jester


One of the main benefits of local labels is that since the same identifier can appear multiple times, they can be used in macros. Consider some hypothetical local label usage like this, though:

   .macro dothething rega regb ptr
   ldrex \regb, [\ptr]
   cmp \rega, \regb
   beq 1
2: <more instructions>
   ...
   strex \regb, \rega, [ptr]
   cmp \regb, #0
   bne 2
1:
   .endm

myfunction:
   dothething r0 r1 r2
   dothething r0 r1 r3
   bx lr

That's actually allowed in armasm (albeit with slightly different syntax), where the behaviour in the absence of a specified direction is "search backwards, then forwards", but still under any reasonable default behaviour at least one of the jumps in the above code is going to end up targeting the wrong instance of a label. Explicitly calling out the direction with beq 1f and bne 2b in the macro resolves the ambiguity and generates the right jumps in both invocations of the macro.

If you choose to use something that isn't a true local label, then not only do you potentially clutter up your symbol table with junk, but you also rob yourself of being able to use loops or conditional branching in macros since you'd generate non-unique symbols. My example might seem a bit contrived, but switch from assembler macros to inline asm blocks in C functions which get inlined all over your complex codebase, and things get a lot more real.

like image 37
Notlikethat Avatar answered Nov 20 '22 17:11

Notlikethat