Search code examples
assemblymasmx86-16dosbox

Call fix array procedure seems to be causing an infinite loop


I wrote this code to draw a shape using video ram. Whenever i call fixarray it seems to go into an infinite loop.Could you please help? I posted a big chunk of code so anyone can regenerate it and figure out what's causing the problem.

            Data_segment_name segment para

            hhead dw ?                 ;head
            h       dw    12 dup  (?)  ;array
            hlength dw ?               ;array length
            htail dw ?                 ;array tail
            Data_segment_name ends


            Stack_segment_name segment para stack
            dw 16 dup(0)             ;define your stack segment
            Stack_segment_name ends


            Code_segment_name segment
            Main_prog proc far

            assume SS:Stack_segment_name,CS:Code_segment_name,DS:Data_segment_name

            mov AX,Data_segment_name  ;load the starting address of the data
            mov DS,AX                 ; segment into DS reg.

            call cls
            call drawh
            call movehu


            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            mov ax,4c00h ; exit program
            int 21h

            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            fixharr proc near
                                        ;fix array positions 
            mov cx,hlength-1            ;i.e (don't need old tail)
            fixarr:
            mov si,cx
            add si,si                   ;scale si to 2
            mov ax,h[si-2]
            mov h[si],ax                
            loop fixarr    
            mov ax,hhead           
            mov h[0],ax   

            ret
            fixharr endp 
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            drawh proc near            ;draw array
            push ax
            push cx
            mov di,160*9+20*2
            mov hhead,di
            mov si,0
            mov h[si],di               ;save head position
            inc si   
            mov hlength,si             ;length = si+1 i.e. h[0]=position length=1
            mov ax,0b800h
            mov es,ax
            mov ax, 1f2ah              ;draw head
            std
            stosw

            mov cx,2
            label1: 
                                       ;draw array
                    mov h[si],di       ;save body position (si is already incremented)
                    mov htail,di
                    inc si             ;to be ready for next insertion
                    mov hlength,si
                    mov ax,0b800h
                    mov es,ax
                    mov ax, 112ah 
                    std
                    stosw
            loop label1

            pop cx
            pop ax
            ret
            drawh endp
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            movehu proc near

            mov ax,hhead               ;remove old head
            mov di,hhead               
            mov ax,0b800h
            mov es,ax
            mov ax,112ah 
            stosw


            mov ax,hhead               ;draw new head (without deleting old head)
            sub ax,160                                  
            mov hhead,ax              
            mov di,hhead               
            mov ax,0b800h
            mov es,ax
            mov ax,1f2ah 
            stosw           
                                       ;delete tail 
            mov di,htail
            mov ax,0b800h
            mov es,ax
            mov ax,002ah
            cld
            stosw
            mov htail,di
                                        ;fix array positions 
            call fixharr
            ret
            movehu endp 
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            cls proc near
            mov ax,0b800h
            mov es,ax
            mov ax,0720h
            mov di,0
            mov cx,2000
            rep stosw 
            ret
            cls endp
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            Code_segment_name ends
            end Main_prog

Solution

  • See, this is why MCVE is important. Now we know that you declared hlength as a variable in memory and not as a constant. For a constant, you can do mov cx, hlength-1 but for a variable that doesn't do what you think. Rewriting in "bracket syntax" that is mov cx, [hlength-1], which loads a word from memory at address hlength-1. It does not load a word from address hlength subsequently decrementing it. To achieve this (since this is what you really want) you should do:

    mov cx, hlength
    dec cx
    

    (or equivalent)

    PS: We have told you the problem is probably with the length even without seeing your full code. Learn to use a debugger.