2015-09-01 3 views
5

Я сейчас читаю tutorial на развитие Raspberry Pi OS и было интересно, о том, как локальные метки используются в этом фрагменте кода (GCC ARM ассемблер):ARM Монтаж локальных меток

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

Если вы используете 1: в качестве метки вы должны указать либо f, либо b после инструкции перехода, чтобы ассемблер знал, в каком направлении нацелен прыжок. Насколько я знаю, вы также можете использовать это:

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

Я думаю, что этот вариант гораздо менее запутанный (локальные метки также отмечены точкой в ​​сборке x86), потому что нет никакого дополнительного письма после метки Справка. Я проверил полученный машинный код, и это то же самое. So мои вопросы:

  • Зачем вам использовать один вариант по сравнению с другим?

  • Для чего необходимо указать направление прыжка либо f, либо b?

+0

Я думаю, что ваше использование местных ярлыков неверно. Это те, что были в форме «N:». «.L» - это имена локальных символов. Причина, по которой вы хотите использовать локальные метки, заключается в том, что в большом файле сборки вы можете определить два «.Loop:», например, а затем ассемблер будет жаловаться на это. Подумайте, например, если вы скопируете вставить другую часть сборки. Вы не можете быть уверены, что не столкнетесь с конфликтом имен. Таким образом, требуются локальные метки. (Https://sourceware.org/binutils/docs/as/Symbol-Names.html) – auselen

ответ

6

Важным отличием является то, что пронумерованные локальные метки могут быть повторно использованы без проблем, и поэтому вам также необходимо указать направление. Вы можете перейти к предыдущему или следующему за ним, но не к ним.

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

Пока вы используете их только в пределах только одного блока, вы можете быть уверены, что они будут работать по назначению и не конфликтует ни с чем другим.

1

Одним из основных преимуществ локальных меток является то, что, поскольку один и тот же идентификатор может появляться несколько раз, они могут использоваться в макросах. Рассмотрим некоторые гипотетические локальное использование метки, как это, хотя:

.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 

Это фактически позволило в armasm (хотя и с немного другой синтаксис), где поведение при отсутствии определенного направления «поиск в обратном направлении, а затем вперед», но все же при любом разумном поведении по умолчанию, по крайней мере, один из прыжков в указанном выше коде будет нацелен на неправильный экземпляр метки. Явным образом вызывая направление с beq 1f и bne 2b в макросе разрешает неоднозначность и генерирует правильные прыжки в обоих вызовах макроса.

Если вы решили использовать что-то, что не является настоящей локальной меткой, то вы не только помешаете вашей таблице символов с помощью мусора, но также можете ограбить себя от использования циклов или условного ветвления в макросах, поскольку вы создадите не уникальные символы. Мой пример может показаться немного надуманным, но переключитесь с ассемблерных макросов на встроенные блоки asm в функциях C, которые входят в состав всей сложной кодовой базы и things get a lot more real.

Смежные вопросы