assemblypixelgame-developmentx86-16bios

assembly 8086 space invaders project, int 10h doesnt work


im making a space invaders project to school and im trying to check if the aliens got to the button of the screen. i used the int 10h d (it takes the color of a pixel on the screen) on my code and it stuck every thing, i tried to understand what happened and came to the conclusion that the line "mov ah,0Dh" along with the "int 10h" line makes it stuck. does anybody has any idea what i can do in order to make it work?

(this is the code)

proc checkAliensDown
pusha
push ax

    mov cx,320           ;loop counter
    checkPixel:          
    push cx

        mov bh,0h
        mov cx,[x]
        mov dx,140
        mov ah,0Dh
        int 10h

        ;the output of the int 10h goes into al
        cmp al,10        ;check if the color of the pixel is green
        jne notDown      ;if not jumps to notDown
            
            mov [lost],1     ;if it is green moves to lost 1
            jmp endProc      ;if it found that the pixel is green it jumps to the end of the proc
            
        notDown:
            
        inc [x]             ;increasing x var in order to check all the pixels in the row, if one of them is green the player lost
        
    pop cx
    loop checkPixel

    endProc:

pop ax
popa
ret
endp checkAliensDown

i tried to push and pop ah and it didn't work


Solution

  • The stack gets un-balanced!

    Random data on the stack is used as the return address, and that crashes the program.

    The push cx right below checkPixel is still on the stack when your code jumps to endProc (in case the green alien got to the bottom of the screen). Simply add a pop cx to remove it:

    mov [lost],1     ;if it is green moves to lost 1
    pop cx
    jmp endProc
    

    Alternatively, use another register to control the loop:

    mov SI,320           ;loop counter
    checkPixel:
        mov bh,0h
        mov cx,[x]
        mov dx,140
        mov ah,0Dh
        int 10h
        cmp al,10        ;check if the color of the pixel is green
        jne notDown      ;if not jumps to notDown
            
            mov [lost],1     ;if it is green moves to lost 1
            jmp endProc
        notDown:
        inc [x]
    dec  SI
    jnz  checkPixel
    endProc:
    

    Tip: the push ax that follows pusha is quite useless. AX is already preserved through pusha. Same applies to the pop ax right before popa.

    i tried to push and pop ah and it didn't work

    It is normal not being able to push or pop a byte-sized register. In the stack operates in word-sized chunks.


    Your checkAliensDown proc depends on the x variable to contain 0 beforehand. I would suggest you add that to the proc:

    proc checkAliensDown
    pusha
    mov word [x], 0
    

    Bonus

    The best solution for this 8086 task where pusha and popa are not valid instructions:

    proc checkAliensDown
     push ax
     push bx
     push cx
     push dx
    
     mov  [lost], 1 ; Guarantees LOST contains a sensible value upon return
     mov  dx, 140   ; Y
     xor  cx, cx    ; X
     mov  bh, 0     ; Page
    checkPixel:
     mov  ah, 0Dh   ; BIOS.ReadPixel
     int  10h       ; -> AL
     cmp  al, 10    ; Is it green?
     je   endProc   ; Jump one time, but have the majority case fall through
     inc  cx
     cmp  cx, 320   ; Use CX for both the X coordinate and the loop counter
     jb   checkPixel
     mov  [lost], cl ; CL=0
    endProc:
    
     pop  dx
     pop  cx
     pop  bx
     pop  ax
     ret
    endp checkAliensDown