Проблема с вызовом нескольких меток / функций в сборке - PullRequest
0 голосов
/ 17 октября 2018

Недавно я изучал программирование на ассемблере и пытаюсь составить программу для задания.У меня есть функция / метка, которая рисует линию на экране.

Проблема в том, что после первого вызова функции она не вызывается во второй раз.Я использую «bl label» для вызова функции и «bx lr» для возврата к точке входа.

Используемый мной компилятор - FASM v1.43, работающий на Raspberry Pi 2

часть основного файла, отвечающая за вызов drawline:

mov r4, #309 ;x
mov r5, #219 ;y

;draw veritcal line   
push{r11,r10,r5,r4}

;vertical or horizontal
mov r10,#1

;length
mov r11,$0100
orr r11,$0003

bl drawline
pop{r4,r5,r10,r11}

;draw second vertical line
push{r11,r10,r5,r4}
mov r10,#1
mov r4, #349 ;x
mov r11,$0100
orr r11,$0003

bl drawline
pop{r4,r5,r10,r11} 

код в drawline, который вызывается:

rect_vloop:
   push {r0-r3}
   mov r0,r7    ;screen address
   mov r1,r4 ;x
   mov r2,r5 ;y
   mov r3,r6 ;colour
     ;assume BITS_PER_PIXEL, SCREEN_X are shared constants
   bl drawpixel
   pop {r0-r3}

;increment and test
   add r5,#1
   mov r8,r11
   cmp r5,r8
bls rect_vloop

dl_end:
bx lr  

Я не писал drawpixel и уже знаю, чтоэто работает.

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

Заранее спасибо.

1 Ответ

0 голосов
/ 17 октября 2018

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

Приложение ARMДвоичный интерфейс обозначает r0-r3 для передачи параметров и возвращаемых значений, поэтому сохранение значений r0-r3 в вашей функции является неправильным.Действительно, ABI утверждает, что

Подпрограмма должна сохранять содержимое регистров r4-r8, r10, r11 и SPr9 в вариантах PCS, которые обозначают r9 as v6)

и если вы не уверены, какой статус r9 находится на вашей платформе, играйте безопасно и сохраните его тоже.

Так что вам нужносохранить что-нибудь важное в r0-r3 и r12 перед вызовом функции и сохранить r4-r11 внутри нее.Вам также необходимо убедиться, что использование стека функции сбалансировано, следовательно, сохраняется sp (r13).

Вы также должны сохранить регистр связи (lr, r14), если ваша функциявызывает любые другие функции, в противном случае вы теряете свой обратный адрес (этот шаг также отсутствует в drawline как написано).

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

К вашему сведению порядок регистров в вашем *Инструкции 1038 * и pop (на самом деле STMDB и LDMIA) не имеют значения;инструкции кодируются битовыми полями, описывающими регистры, которые должны быть сохранены или загружены, и порядок, в котором они хранятся и извлекаются, соответствует возрастающим номерам регистров, занимающим восходящие ячейки памяти.Большинство сборщиков ARM предупредит вас, если вы попытаетесь указать список регистров в любом другом порядке, кроме как в порядке возрастания, поскольку они предполагают, что вы пытаетесь получить какую-то конкретную загрузку или порядок хранения, который вы не получите.

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

...