Search code examples
assemblyx86-16masm

Assembly maze solver not modifying si di and bx registers


I'm trying to program a maze solver in assembly. We are given a driver program that sends the current x position in the si register, the y position in the di register, the moving direction in the bx register and the maze itself in the bp register.

I'm supposed to check to see if the mouse can move left, then forward, then right then back.

My problem is that when i try to run this it doesnt seem to be modifying the si di or bx registers and i cannot find out why.

Can someone please look to see if there are any glaring issues that might be causing this. I never post on here but im running out of options thank you very much.

;---------------------------------------------------------------------
; Program:   nextval subroutine
;
; Function:  Find next mouse move in an array 15 by 30.
;            We can move into a position if its contents is blank ( 20h ).
;
; Input:     Calling sequence is:
;            x    pointer   si
;            y    pointer   di
;            dir  pointer   bx  E=1 S=2 W=3 N=4
;            maze pointer   bp
;
; Output:    x,y,dir modified in caller's data segment
;
; Owner:     Dana A. Lasher
;
; Date:      Update Reason
; --------------------------
; 11/06/2016 Original version
;
;
;---------------------------------------
         .model    small               ;64k code and 64k data
         .8086                         ;only allow 8086 instructions
         public    nextval             ;allow extrnal programs to call
;---------------------------------------


;---------------------------------------
         .data                         ;start the data segment
;---------------------------------------
value db 30
;---------------------------------------
         .code                         ;start the code segment
;---------------------------------------
; Save any modified registers
;---------------------------------------
nextval:
    push   cx                          ; save cx register
    mov    cl, 0                       ; set testing phase to 0 stored in ch
;---------------------------------------
; Code to make 1 move in the maze
;---------------------------------------

testnext:
    push   ax                          ; save ax register
    push   dx                          ; save dx register
    push   bx                          ; save bx register
    push   si                          ; save si register
    push   di                          ; sav  di register
    mov    dh, [si]                    ; load the x value into dh
    mov    dl, [di]                    ; load the y value into dl
    inc    cl                          ; increment the testing phase

direction:
    cmp    word ptr [bx], 1            ; is the moving direction East
    je     goingeast                   ; yes, jump to the going east function
    cmp    word ptr [bx], 2            ; is the moving direction south
    je     goingsouth                  ; yes, jump to the going south function
    cmp    word ptr [bx], 3            ; is the moving direction west
    je     goingwest                   ; yes, jump to the going west function
    cmp    word ptr [bx], 4            ; is the moving direction north
    je     goingnorth                  ; yes, jump to the going north function
    jmp    exit
;---------------------------------------
; Going East        Check order: N-E-S-W
;---------------------------------------
goingeast: 
    cmp    cl, 1                       ; is the testing phase phase 1
    je     checknorth                  ; yes, check to see if a move north is valid
    cmp    cl, 2                       ; is the testing phase phase 2
    je     checkeast                   ; yes, check to see if a move east is valid
    cmp    cl, 3                       ; is the testing phase phase 3
    je     checksouth                  ; yes, check to see if a move south is valid 
    cmp    cl, 4                       ; is the testing phase phase 4
    je     checkwest                   ; yes, check to see if a move west is valid 
    jmp    exit 
;---------------------------------------
; Going South       Check order: E-S-W-N
;---------------------------------------
goingsouth:
    cmp    cl, 1                       ; is the testing phase phase 1
    je     checkeast                   ; yes, check to see if a move east is valid
    cmp    cl, 2                       ; is the testing phase phase 2
    je     checksouth                  ; yes, check to see if a move south is valid 
    cmp    cl, 3                       ; is the testing phase phase 3
    je     checkwest                   ; yes, check to see if a move west is valid 
    cmp    cl, 4                       ; is the testing phase phase 4
    je     checknorth                  ; yes, check to see if a move north is valid
    jmp    exit 
;---------------------------------------
; Going West        Check order: S-W-N-E
;---------------------------------------
goingwest: 
    cmp    cl, 1                       ; is the testing phase phase 1
    je     checksouth                  ; yes, check to see if a move south is valid 
    cmp    cl, 2                       ; is the testing phase phase 2
    je     checkwest                   ; yes, check to see if a move west is valid 
    cmp    cl, 3                       ; is the testing phase phase 3
    je     checknorth                  ; yes, check to see if a move north is valid
    cmp    cl, 4                       ; is the testing phase phase 4
    je     checkeast                   ; yes, check to see if a move east is valid
    jmp    exit 
;---------------------------------------
; Going North       Check order: W-N-E-S
;---------------------------------------
goingnorth:
    cmp    cl, 1                       ; is the testing phase phase 1
    je     checkwest                   ; yes, check to see if a move west is valid 
    cmp    cl, 2                       ; is the testing phase phase 2
    je     checknorth                  ; yes, check to see if a move north is valid
    cmp    cl, 3                       ; is the testing phase phase 3
    je     checkeast                   ; yes, check to see if a move east is valid
    cmp    cl, 4                       ; is the testing phase phase 4
    je     checksouth                  ; yes, check to see if a move south is valid 
    jmp    exit 
;---------------------------------------
; Check East                X + 1 Y same
;---------------------------------------
checkeast:
    inc    byte ptr [si]               ; increment the x position
    inc    dh                          ; incremement dh to the x position being tested
    mov    ch, 1                       ; update the testing direction ch to 1
    jmp    testposition                ; jump to the test position function
;---------------------------------------
; Check South               X same Y + 1
;---------------------------------------
checksouth:
    inc    byte ptr [di]               ; increment the y position
    inc    dl                          ; increment dl to the y position being tested
    mov    ch, 2                       ; update the testing direction ch to 2
    jmp    testposition                ; jump to the test position function
;---------------------------------------
; Check West                X - 1 Y same
;---------------------------------------
checkwest:
    dec    byte ptr [si]               ; decrement the x position
    dec    dh                          ; update dh to the x position being tested
    mov    ch, 3                       ; update the testing direction ch to 3
    jmp    testposition                ; jump to the test position function
;---------------------------------------
; Check North               X same Y - 1
;---------------------------------------
checknorth:
    dec    byte ptr [di]               ; increment the y position
    dec    dl                          ; update dl to the y position being tested
    mov    ch, 4                       ; update the testing direction ch to 4

testposition:
    mov    ax, [di]                    ; move the y position being tested into the ax register
    dec    ax                          ; decrement the ax register for the offset calculation
    mul    [value]                     ; multiply the al register by 30 and store the product in ax
    add    ax, [si]                    ; add the x position to the ax
    dec    ax                          ; decrement the ax register for the offset calculation
    mov    [si], ax                    ; move the offset calculated inside of ax into si
    mov    ax, ds:[bp + si]            ; access the maze using data segment override with the offset in si
    cmp    ax, 20h                     ; position in the maze at the offset empty
    je     exit                        ; yes jump to the exit function
    pop    di                          ; no, restore the di register
    pop    si                          ; no, restore the si register
    pop    bx                          ; no, restore the bx register
    pop    dx                          ; no, restore the dx register
    pop    ax                          ; no, restore the ax register
    jmp    testnext                    ; test the next move direction
;---------------------------------------
; Restore registers and return
;---------------------------------------
exit:
    pop    di                          ; restore the di register
    pop    si                          ; restore the si register
    pop    bx                          ; restore the bx register

    ; here the dx and cx registers should still have the needed information
    mov    byte ptr [si], dh           ; update x position
    mov    byte ptr [di], dl           ; update y position
    mov    byte ptr [bx], ch           ; update moving direction

    pop    dx                          ; restore the dx register
    pop    ax                          ; restore the ax register
    pop    cx                          ; restore the cx register
    ret                                ; return
;---------------------------------------
    end    nextval

Solution

  • ; Output: x,y,dir modified in caller's data segment

    Given this sentence in the preamble, I think it's rather a good thing that the SI, DI, and BX registers are not modified by your maze solver...

    Destroying the input data prematurely

    One of the problems in your code is that you destroy the original data while testing is in progress. And because you need to test several times over, the subsequent tests will be using garbage data.
    Within the procedure you must only work from the local copies of X and Y that you loaded in the DH and DL registers.

    These have to go:

    inc    byte ptr [si]               ; increment the x position
    inc    byte ptr [di]               ; increment the y position
    dec    byte ptr [si]               ; decrement the x position
    dec    byte ptr [di]               ; increment the y position
    

    A bogus address calculation

    mov    [si], ax         ; move the offset calculated inside of ax into si
    
    • This instruction does not what the comment says. That would be mov si, ax.
      And just as important, you should not be destroying SI at this point in the program!

    • From the dec ax instructions in the testposition part, we see that you expect X and Y to be 1-based coordinates. That's fine but you must use the locally modified values in DH and DL in the calculation:

    • The offset address calculation suits a byte-sized array (the maze). Therefore you should not be compairing a word from it!

    Try next code:

    mov    al, DL           ; move the y position being tested into the AL register
    dec    al               ; decrement the AL register for the offset calculation
    mul    [value]          ; multiply the al register by 30 and store the product in ax
    add    al, DH           ; add the x position to the ax
    adc    ah, 0
    dec    ax               ; decrement the ax register for the offset calculation
    push   si               ; Preserve SI
    mov    si, ax           ; move the offset calculated inside of ax into si
    mov    al, ds:[bp + si] ; access the maze using data segment override with offset si
    pop    si               ; Restore SI
    cmp    al, 20h          ; position in the maze at the offset empty
    je     exit             ; yes jump to the exit function
    

    One final concern

    Are you sure that the direction variable dir is actually a word. I would sooner expect to find that small value in a byte-sized variable.