2016-03-06 2 views
0

Я пытаюсь написать очень простой кросс-компилятор для малины Pi B + Version для создания простых простых металлических программ. Мой компилятор способен переводить простые команды в соответствующую инструкцию машинного языка, используя таблицу набора инструкций ARM.ARMv6 Branch in Bare Metal Programming (Raspberry Pi B +)

Включение светодиодов (ориентируется на курс выпечки, http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/) работает отлично.

Но теперь я хочу сделать некоторые инструкции ветвления, и это, где ничто не похоже на работу больше:

Во-первых, я хотел бы перейти к абсолютному адресат, не относительные ветви с помощью B/BL инструкция.

Чтобы проверить ветку, я использую следующий код разобранном (разобран с помощью Хоппер дизассемблер V3 тестовой версии), которым включается светодиодный индикатор, связанный с GPIO 16 and22:

00000000 mov r0, #0x20000000  ;Load the GPIO Base Address into R0 
00000004 orr r0, r0, #0x200000 
00000008 mov r1, #0x40   ;Load the Set Function Mask (for GPIO 22) into r1 
0000000c str r1, [r0, #0x8]  ;Store the Set Function Mask into the GPFSEL2 
00000010 mov r1, #0x400000  ;Move the Set Output Mask (for GPIO 22) into r1 
00000014 str r1, [r0, #0x1c]  ;Store the Set Output Mask into GPSET0 

00000018 mov r0, #0x20000000  ;Load the GPIO Base Address into R0 
0000001c orr r0, r0, #0x200000 
00000020 mov r1, #0x40000  ;Load the Set Function Mask (for GPIO 16) into r1 
00000024 str r1, [r0, #0x4]  ;Store the Set Function Mask into the GPFSEL2 
00000028 mov r1, #0x10000  ;Move the Set Output Mask (for GPIO 16) into r1 
0000002c str r1, [r0, #0x1c]  ;Store the Set Output Mask into GPSET0 

00000030 b 0x30     ;Infinity Loop to keep the processor up 

Теперь я хочу добавьте ветвь в начало кода, чтобы пропустить первый раздел, так что активируется только второй светодиод.

Я пробовал так:

mov r15, #0x1c 

но единственный эффект, что оба светодиода оставаться темным.

Моя вторая попытка как то:

mov r2, #0x20 
bx r2 

Но что ни работ.

Так что мой вопрос:

  • Как выполнить такую ​​ветку?
  • Я использую адреса правильно?
+0

Это может сделать интересное упражнение по обучению, gcc имеет опцию '-ffreestanding' для создания кода, который не зависит от каких-либо библиотек. Я предполагаю, что ассемблер GNU может собрать ARM asm в плоский двоичный файл, если вы его попросите, поэтому вы можете использовать его для записи кода запуска, который устанавливает для запуска ваших функций вывода компилятора. Насколько я понимаю, это как раз то, как ядро ​​Linux построено: в основном C с некоторым asm для установки, и процесс сборки, который делает образ ядра вместо исполняемого файла ELF. –

ответ

0

Благодаря подсказке из @TimothyBaldwin я получил теперь ответ (я надеюсь, что его хорошо, если бы я написать собственные ответы предоставляя более подробную информацию, а не просто принимая его).

Как упоминалось в @TimothyBaldwin, проблема заключалась в том, что программа загружается на 0x8000, как вы можете видеть на диаграмме, найденной по адресу https://raspberrypi.stackexchange.com/questions/10442/what-is-the-boot-sequence.

Как пояснялось там, в моем случае это отлично работает хорошо, если добавить к моему config.txt следующую строку:

disable_commandline_tags=1 

, потому что тогда код загружается в 0x0, и все работает, как ожидалось.

0

Вы введете неправильный адрес, программа загружена на 0x8000. Если вы используете метки, компоновщик должен рассчитать адреса для вас.

+0

Откуда у вас эта информация? На данный момент я не использую ассемблер/компоновщик, потому что я хотел бы сделать это самостоятельно для обучения. – Marben

+0

Лучшее место для обучения - это инструменты, которые работают. используйте gnu binutils, чтобы собрать, затем разобрать и посмотреть, как инструкции создаются в качестве документа для рук в то время как хорошо, не всегда рисуйте точную картину для каждой ситуации. –

+0

, или если вы откажетесь использовать рабочий ассемблер, то, по крайней мере, используйте дизассемблер, чтобы проверить созданный код. –

0

Хотя я не знаю, регистры Raspbery Pi, я думаю, что есть несколько проблем, в этом коде:

  • Эта программа, кажется, чтобы включить светодиод, не выключен. Поэтому даже если вы введете ветку, она не будет мигать. Вам нужен регистр, в котором вы инвертируете значение, чтобы светодиод был включен/выключен во время циклов.
  • Без некоторой задержки это будет слишком быстро, чтобы увидеть, как светодиод мигает. Вы можете либо добавить задержку (функция библиотеки), прерывание от таймера, либо просто цикл for (который будет ветвью).

Кстати, для цикла для задержки может быть что-то вроде:

 MOV r0, #1000 ; Start of the counter 
loop: SUBS r0, #1  ; Decrement the counter (Sets the flags for the branch) 
     BNE loop  ; Branch to loop label until r0 is 0 
+0

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

1

Bx или BLX должен быть вашим первым выбор для получения инструкций. Вы можете появиться на компьютере, но зачем настраивать регистр, push и pop, просто bx. И могут быть и другие, которые могут правильно модифицировать компьютер, но не уверены, что mov - это одно, но вам будут сообщать документы.

Если bx не работает для вас, вы либо ошибочно кодируете ошибку bx, либо неправильно указываете адрес в регистре.

mov r3,#0x12000000 
orr r3,r3,#0x00340000 
orr r3,r3,#0x00005600 
orr r3,r3,#0x00000078 
bx r3 

производит

0: e3a03412 mov r3, #301989888 ; 0x12000000 
    4: e383370d orr r3, r3, #3407872 ; 0x340000 
    8: e3833c56 orr r3, r3, #22016 ; 0x5600 
    c: e3833078 orr r3, r3, #120 ; 0x78 
    10: e12fff13 bx r3 

и разветвляются обратиться 0x12345678

+0

, и при необходимости вы можете столкнуться с условным полем. –