2013-11-16 3 views
0

У меня было несколько вопросов относительно значения некоторых мнемоник и команд, которые присутствуют в коде, который мне давался. Я никогда раньше не работал с Ассамблеей.Код дешифрующей сборки

Вот фрагмент кода:

traverse proc 
     ldr r0, =21475234 
     push {r4, r5, lr} 
     mov r4, r0 
     ldr r5, [r4] 

     ldr r0, [r4, #4] 
     bl traverse 
     cmp r5, r0 
     it lt 
     movlt r5, r0 

     mov r0,r5 
     pop {r4,r5,pc} 
  1. Что именно загружается в r5? Следуя инструкциям, удаляет r4 в стек, загружается со значением r0, а затем загружается r5?

  2. Что загружается в r0? [r4, #4] ссылается на номер в пятой позиции в r4?

  3. bl traverse Поскольку мы уже работаем в функции траверса, мы связываем ветку с одной и той же функцией?

  4. Я не уверен, что имеется в виду под номером pc Мнемоника.

  5. Что делает proc в traverse proc символизировать? Нужно ли это в объявлении каждой функции?

Спасибо заранее, я все еще пытаюсь понять это.

+0

Это рекурсивная функция, которая не завершается. Здесь что-то сломалось. –

ответ

1
ldr r0, =21475234 

Это ярлык, почти псевдокод. Различные кронштейны рычагов имеют тенденцию поддерживать его.

Вероятно, предполагается использовать как этот

ldr r0,=hello 
ldr r1,[r0] 

... 

in some other file perhaps 

.globl hello 
hello: 
    .word 0x1234 

В основном это означает, что загрузить адрес вещи после знака равенства.

ldr r0,hello 
... 
hello: 
    .word 0x1234 

говорит, что загружает значение данных на ярлыке hello в r0.

В C именно это

//ldr r0,=hello 
unsigned int r0 = (unsigned int)&hello; 
//ldr r0,hello 
unsigned int r0 = hello; 

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

ldr r0,=0x12345678 

, который кодируется как

ldr r0,temp000 
... 
temp000: .word 0x12345678 

Загрузите значение 0x12345678 в r0. Ассемблеру необходимо найти место, достаточно близко к ldr, но с пути исполнения, чтобы разместить это слово данных, и иногда вы получите сообщение об ошибке, которое не может найти место.

Так

ldr r0, =21475234 

Загружает значение 21475234 в r0.

Этот пуск push {r4, r5, lr} сохраняет r4, r5 и регистр возврата lr в стеке. Обычно используемое соглашение о вызове говорит, что для руки вы можете уничтожить r0-r3, но вы должны сохранить другие регистры (есть два или два исключения), поэтому для использования r4 мы должны его сохранить. Я предполагаю, что это был скомпилированный код, не написанный вручную, и/или он вызван из скомпилированного кода?

так что теперь мы можем использовать r4, это копирует значение 21475234 в r4, r0 и r4 держать то же самое для теперь мов r4, r0 , когда вы кладете [скобки] вокруг регистра, в основном регистре косвенную адресация, вместо желания содержимое этого регистра, содержимое этого регистра адреса для содержимого, которое необходимо, так это говорит прочитать значение по адресу 21475234 и сохранить это значение в r5

ldr r5, [r4] 

вы убрали код здесь для публикации этого вопроса?

это говорит прочитать значение по адресу 21475234 + 4 и кроме того, что в r0

ldr r0, [r4, #4] 

Когда непосредственное значение в скобках, что означает добавить, что в регистр и использовать этот адрес для чтения с адреса в регистр r4 плюс 4.

ldr r0, [r4, #4] 

чтения с адреса, полученного путем добавления r4 + r5

ldr r0, [r4, r5] 

это совсем другое, это говорит, прочитанный с адреса в r4, поместите значение в r0 THEN ADD 4 TO R4.

ldr r0, [r4], #4 

Это будет похоже на код C

unsigned int r0 = *r4++; 

Л.Р. является регистр ссылки r14, рс счетчика программы r15, когда вы меняете r15 это эффективно филиал. Нажатие lr сохраняло адрес возврата, когда вызывалась функция (процедура, proc) таким образом, что вы можете вернуться к запущенному коду сразу после вызова функции. Для этого вам необходимо поменять счетчик программ на адрес, который находится сразу после вызова (bl = ветвь связи, которая в основном является вызовом функции на какой-либо адрес). Так что в руке вы можете нажать Ьги и поп-ПК, так что

pop {r4,r5,pc} 

является дополнением к толчку, он восстанавливает r4 и r5 к значениям, которые были там, когда функция была введена, а затем выталкивает возвращение адрес в счетчик программ, чтобы программа перешла на этот адрес.

traverse - это метка или название процедуры (функции), процедура краткая для процедуры. Несомненно, сборщик-мнемоник, который более специализирован, чем просто объявление метки. Ярлык должен работать нормально, но вы можете получить дополнительную помощь от ассемблера, если вы это сделаете. (Я никогда не нашел причины делать это за 20 лет работы над сборкой ежедневно, но, возможно, у других есть).

bl traverse, это рекурсивный вызов. Не знаете, как вы выходите из этого, вы опубликовали весь код?

+0

Ничего себе. Большое спасибо! На ваш ответ был дан подробный и информативный ответ на мои вопросы. Это определенно прояснилось.Однако у меня был еще один вопрос. Вы упомянули, что ldr r0, [r4, # 4] загружается в r0, адрес r4 +4. Так как r4 находится в стеке, добавление +4 к адресу r4 даст адрес r5 в стеке? Я не оставил ни одного из кода. Нам дали это как упражнение написать на C, а затем объясните в своих собственных словах, как работает этот код/​​цель программы. Еще раз спасибо за вашу помощь, я ценю это! –

+1

r4 - это регистр, копия которого находится в стеке. Точно так же, как r0 и r4 в течение некоторого периода времени в этом коде имеют одинаковое значение. Стек - это просто память (некоторые биты), а регистр - несколько бит, они являются отдельными. Цель размещения значения в стеке заключается в том, чтобы гарантировать, что мы вернем r4 так, как мы его нашли, когда закончим с функцией, в основном мы не хотим касаться этого значения в стеке. –

+0

Абсолютно блестящий. Спасибо, dwelch :) –