title: Getting a byte from a maze using offset calculation Assembly
body: <p>For this project I am given a maze represented as an array of bytes that either contains 20h (empty space that can be moved into) or anything else (full space that cannot be moved into)</p>
  <p>From the driver program I am given</p>
  <pre><code>x    pointer   si
  y    pointer   di
  dir  pointer   bx  E=1 S=2 W=3 N=4
  maze pointer   bp
  </code></pre>
  <p>I have figured out how to modify the registers once I determine if a space is empty and have also calculated the offset into the maze at which the byte I'm testing resides.</p>
  <p>The formula: (Y-1) * 30 + (X-1) calculates the offset of the byte I want to test into the array. 30 is the width of the maze.</p>
  <p>So essentially I need to do something like</p>
  <p>mov al, ds:[bp + ((Y-1) * 30 + (X-1))]</p>
  <p>and then compare the byte stored in al from the maze with 20h to see if i can move to that position</p>
  <p>my current code for this is: which works correctly</p>
  <pre><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
      jne    testnext             ; yes jump to the exit function              
  </code></pre>
  <p>we are graded on efficiency and its noted that we could use &quot;advanced indirect addressing to avoid doing all of this offset calculation in ax so if you know how that could be done i would be incredibly grateful.</p>
  <p>here is the full code:</p>
  <pre><code>;---------------------------------------------------------------------
  ; 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
      push   ax                          ; save ax register
      push   dx                          ; save dx register
      mov    cl, 0                       ; set testing phase to 0 stored in ch
  ;---------------------------------------
  ; Code to make 1 move in the maze
  ;---------------------------------------
  
  testnext:
      mov    ax, 0
      mov    dx, 0
      mov    dh, [si]
      mov    dl, [di]
      inc    cl                          ; increment the testing phase
  
  direction:
      cmp    byte ptr [bx], 1            ; is the moving direction East
      je     goingeast                   ; yes, jump to the going east function
      cmp    byte ptr [bx], 2            ; is the moving direction south
      je     goingsouth                  ; yes, jump to the going south function
      cmp    byte ptr [bx], 3            ; is the moving direction west
      je     goingwest                   ; yes, jump to the going west function
      cmp    byte 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    dh                          ; incremement dh to the x position being tested
      mov    ch, 1                       ; update the testing direction ch to 1
   
      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
      jne    testnext             ; yes jump to the exit function
   
      inc    byte ptr [si]          ; update x position
      mov    byte ptr [bx], 1           ; update moving direction
      jmp    exit
  ;---------------------------------------
  ; Check South               X same Y + 1
  ;---------------------------------------
  checksouth:
      inc    dl                          ; increment dl to the y position being tested
      mov    ch, 2                       ; update the testing direction ch to 2
  
      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
      jne    testnext             ; yes jump to the exit function
   
      inc    byte ptr [di]          ; update x position
      mov    byte ptr [bx], 2           ; update moving direction
      jmp    exit
  ;---------------------------------------
  ; Check West                X - 1 Y same
  ;---------------------------------------
  checkwest:
      dec    dh                          ; update dh to the x position being tested
      mov    ch, 3                       ; update the testing direction ch to 3
  
      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
      jne    testnext             ; yes jump to the exit function
  
      dec    byte ptr [si]          ; update x position
      mov    byte ptr [bx], 3           ; update moving direction
      jmp    exit
  ;---------------------------------------
  ; Check North               X same Y - 1
  ;---------------------------------------
  checknorth:
      dec    dl                          ; update dl to the y position being tested
      mov    ch, 4                       ; update the testing direction ch to 4
  
      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
      jne    testnext             ; yes jump to the exit function
   
      dec    byte ptr [di]           ; update x position
      mov    byte ptr [bx], 4           ; update moving direction
      jmp    exit
  ;---------------------------------------
  ; Restore registers and return
  ;----------------d-----------------------
  exit:
  
      ; here the dx and cx registers should still have the needed information
      pop    dx                          ; restore the dx register
      pop    ax                          ; restore the ax register
      pop    cx                          ; restore the cx register
      ret                                ; return
  ;---------------------------------------
      end    nextval
  </code></pre>