Алгоритм линии Брезенхэма сборки ARM

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

drawline:
; r0 = screen_address
; r1 = x0
; r2 = y0
; r3 = x1
; r4 = y1
; r5 = colour

push {r6-r10}   ; store the registers we will alter, thoughtful, right?
cmp r1,r3       ; compare x0 and x1
subgt r6,r1,r3  ; deltax = x0 - x1
movgt r7,#-1    ; stepx = -1
suble r6,r3,r1  ; deltax = x1 - x0
movle r7,#1     ; stepx = 1

cmp r2, r4      ; compare y1 and y0
subgt r8,r4,r2  ; deltay = y1 - y0
movgt r9,#-1    ; stepy = -1
suble r8,r2,r4  ; deltay = y0 - y1
movle r9,#1     ; stepy = 1

add r10,r6,r8   ; error = deltax - deltay

line_pixel_loop:
    teq r1,r3
    teqeq r2,r4
    popeq {r6-r10}
    bxeq lr

    push {r3, lr}   ; store registers which we will alter
    ; the following are inferred:
    ; r0 = screen address
    ; r1 = x, current
    ; r2 = y, current
    mov r3,r5       ; colour
    bl drawpixel    ; draw the pixel
    pop {r3, lr}    ; restore the altered registers

    cmp r8,r10, lsl#1   ; compare deltay (now negative) with 2 * error
    addle r10, r8       ; if less than: error += deltay
    addle r1, r7        ; if less than: x0 += stepx

    cmp r6,r10, lsl #1  ; compare deltax with 2 * error
    addge r10, r6       ; if greater than: error += stepx
    addge r2, r9        ; if greater than: y0 += stepy

    ; cmp r1,r3         ; compare x0 and x1
    ; cmpeq r2,r4   ; if equal: compare y0 and y1
    ; bne line_pixel_loop   ; if not equal, continue the loop
    b line_pixel_loop


pop {r6-r10} ; clean up

bx lr ; return

Эти две линии рисуются без проблем:

push {r0-r5}
mov r0,r7     ;screen
mov r1,#300   ;x0
mov r2,#100   ;y0
mov r3,#200   ;x1
mov r4,#200   ;y1
mov r5,r6     ;colour
bl drawline
pop {r0-r5}

push {r0-r5}
mov r0,r7     ;screen
mov r1,#300   ;x0
mov r2,#100   ;y0
mov r3,#400   ;x1
mov r4,#200   ;y1
mov r5,r6     ;colour
bl drawline
pop {r0-r5}

Эта строка не рисуется и не позволяет программе выполняться дальше:

push {r0-r5}
mov r0,r7     ;screen
mov r1,#350   ;x0
mov r2,#265   ;y0
mov r3,#353   ;x1
mov r4,#266   ;y1
mov r5,r6     ;colour
bl drawline
pop {r0-r5}

person Terry    schedule 23.10.2016    source источник
comment
Как отлаживать ARM asm в QEMU на рабочем столе Linux x86   -  person Peter Cordes    schedule 23.10.2016
comment
Так что же именно происходит в вашем коде со строкой, которая не работает? Когда вы выполняете одношаговое выполнение в отладчике или ^c для получения подсказки отладчика во время его работы, какие значения находятся в регистрах? См. Как спросить/минимальный воспроизводимый пример с советами о том, что включать в запрос на помощь по отладке.   -  person Peter Cordes    schedule 23.10.2016
comment
Что ж, я только что прошел через это с «проблемным» вводом в симуляторе, и все выглядело нормально — проблема должна быть связана с drawpixel или вызывающим кодом. Я предполагаю, что это также рукописная сборка (поскольку вы не используете стандартные соглашения о вызовах)?   -  person Notlikethat    schedule 23.10.2016
comment
Использование eq для условия завершения означает, что если вы перешагнете, вы продолжите до тех пор, пока целое не завершится. Ваш проблемный ввод кажется маленьким deltaX=3, deltaY=1. Если вы перешагнёте точку, ваше завершение никогда не произойдёт. Также r10 (ошибка) только добавляется. Разве это не должно чередоваться между положительным и отрицательным? В соответствии с алгоритмом Wiki breshnam вам необходимо добавить/подписать ошибку (заглавную "Д" там). Вы собираетесь рисовать только один квадрант или предполагается, что он справится со всеми?   -  person artless noise    schedule 23.10.2016
comment
godbolt.org/g/tpyeyo — это пример, скомпилированный на языке C.   -  person artless noise    schedule 23.10.2016
comment
Дельта @artlessnoise всегда отрицательная. deltay назначается меньшему y минус большему. Таким образом, когда дельта y добавляется к ошибке, она добавляет отрицательное число.   -  person Terry    schedule 24.10.2016