I'm trying to create a line-drawing algorithm in assembly (more specifically Bresenham's line algorithm). After trying an implementation of this algorithm, the algorithm fails to work properly even though I almost exactly replicated the plotLineLow() function from this Wikipedia page.
It should be drawing a line between 2 points, but when I test it, it draws points in random places in the window. I really don't know what could be going wrong because debugging in assembly is difficult.
I'm using NASM to convert the program to binary, and I run the binary in QEMU.
[bits 16]                                               ; 16-bit mode
[org 0x7c00]                                            ; memory origin
section .text                                           ; code segmant
    global _start                                       ; tells the kernal where to begin the program
_start:                                                 ; where to start the program
; main
call cls                                                ; clears the screen
update:                                                 ; main loop
    mov cx, 0x0101                                      ; line pos 1
    mov bx, 0x0115                                      ; line pos 2
    call line                                           ; draws the line
    jmp update                                          ; jumps to the start of the loop
; functions
cls:                                                    ; function to clear the screen
    mov ah, 0x00                                        ; set video mode
    mov al, 0x03                                        ; text mode (80x25 16 colours)
    int 0x10                                            ; BIOS interrupt
    ret                                                 ; returns to where it was called
point:                                                  ; function to draw a dot at a certain point (dx)
    mov bx, 0x00ff                                      ; clears the bx register and sets color
    mov cx, 0x0001                                      ; clears the cx register and sets print times
    mov ah, 0x02                                        ; set cursor position
    int 0x10                                            ; BIOS interrupt
    mov ah, 0x09                                        ; write character
    mov al, ' '                                         ; character to write
    int 0x10                                            ; BIOS interrupt
    ret                                                 ; returns to where it was called
line:                                                   ; function to draw a line at two points (bx, cx)
    push cx                                             ; saves cx for later
    push bx                                             ; saves bx for later
    sub bh, ch                                          ; gets the value of dx
    mov [dx_L], bh                                      ; puts it into dx
    sub bl, cl                                          ; gets the value of dy
    mov [dy_L], bl                                      ; puts it into dy
    mov byte [yi_L], 1                                  ; puts 1 into yi (positive slope)
    cmp byte [dy_L], 0                                  ; checks if the slope is negative
    jl .negative_y                                      ; jumps to the corresponding sub-label
    jmp .after_negative_y                               ; if not, jump to after the if
    .negative_y:                                        ; if statement destination
        mov byte [yi_L], -1                             ; sets yi to -1 (negative slope)
        neg byte [dy_L]                                 ; makes dy negative as well
    .after_negative_y:                                  ; else statement destination
    mov ah, [dy_L]                                      ; moves dy_L into a temporary register
    add ah, ah                                          ; multiplies it by 2
    sub ah, [dx_L]                                      ; subtracts dx from that
    mov [D_L], ah                                       ; moves the value into D
    pop bx                                              ; pops bx to take a value off
    mov [y_L], bh                                       ; moves the variable into the output
    
    pop cx                                              ; pops the stack back into cx
    mov ah, bh                                          ; moves x0 into ah
    mov al, ch                                          ; moves x1 into al
    .loop_x:                                            ; loop to go through every x iteration
        mov dh, ah                                      ; moves the iteration count into dh
        mov dl, [y_L]                                   ; moves the y value into dl to be plotted
        call point                                      ; calls the point function
        cmp byte [D_L], 0                               ; compares d to 0
        jg .greater_y                                   ; if greater, jumps to the if statement
        jmp .else_greater_y                             ; if less, jumps to the else statement
        mov bh, [dy_L]                                  ; moves dy into a temporary register
        .greater_y:                                     ; if label
            mov bl, [yi_L]                              ; moves yi into a temporary register
            add [y_L], bl                               ; increments y by the slope
            sub bh, [dx_L]                              ; dy and dx
            add bh, bh                                  ; multiplies bh by 2
            add [D_L], bh                               ; adds bh to D
            jmp .after_greater_y                        ; jumps to after the if statement
        .else_greater_y:                                ; else label
            add bh, bh                                  ; multiplies bh by 2
            add [D_L], bh                               ; adds bh to D
        .after_greater_y:                               ; after teh if statement
        inc ah                                          ; increments the loop variable
        cmp ah, al                                      ; checks to see if the loop should end
        je .end_loop_x                                  ; if it ended jump to the end of teh loop
        jmp .loop_x                                     ; if not, jump back to the start of the loop
    .end_loop_x:                                        ; place to send the program when the loop ends
    ret                                                 ; returns to where it was called
section .data                                           ; data segmant
dx_L: db 0                                              ; used for drawing lines
dy_L: db 0                                              ; ^
yi_L: db 0                                              ; ^
xi_L: db 0                                              ; ^
D_L: db 0                                               ; ^
y_L: db 0                                               ; ^
x_L: db 0                                               ; ^
section .text                                           ; code segmant
; boot the OS
times 510-($-$$) db 0                                   ; fills up bootloader space with empty bytess
db 0x55, 0xaa                                           ; defines the bootloader bytes
 
    