【问题标题】:Assembly maze solver not modifying si di and bx registers装配迷宫求解器不修改 si di 和 bx 寄存器
【发布时间】:2021-03-27 02:52:19
【问题描述】:

我正在尝试在汇编中编写一个迷宫求解器。我们得到一个驱动程序,它发送当前 x 位置在 si 寄存器中,y 位置在 di 寄存器中,移动方向在 bx 寄存器中,迷宫本身在 bp 寄存器中。

我应该检查一下鼠标是否可以向左移动,然后向前,然后向右,然后返回。

我的问题是,当我尝试运行它时,它似乎没有修改 si di 或 bx 寄存器,我无法找出原因。

有人可以看看是否有任何明显的问题可能导致此问题。我从不在这里发帖,但我的选择已经不多了,非常感谢。

;---------------------------------------------------------------------
; 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

【问题讨论】:

  • 当然不是修改BX;您的所有指令(pop bx 除外)都没有将 BX 作为目标(或其 BL 或 BH 8 位半部分)。 mov byte ptr [bx], ch 将存储到 BX 指向的内存,如果它运行,但 BX 本身不会被修改。所以我不确定你期待什么样的答案,这对于minimal reproducible example 来说似乎是很多代码。 minimal reproducible example 不需要做任何有用的事情,只需重现您想询问的任何行为。
  • 你先push dx,最后pop dx,然后存入[di]和[si]。所以在这之间完成的所有工作都丢失了。

标签: assembly x86-16 masm


【解决方案1】:

;输出:x,y,dir 修改在调用者的数据段中

鉴于序言中的这句话,我认为 SIDIBX 寄存器被您的迷宫求解器修改是一件好事...

过早销毁输入数据

您的代码中的一个问题是您在测试过程中破坏了原始数据。而且由于需要多次测试,后续的测试将使用垃圾数据。
在该过程中,您只能使用您在 DHDL 寄存器中加载的 XY 的本地副本。

这些必须去:

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

虚假地址计算

mov    [si], ax         ; move the offset calculated inside of ax into si
  • 此说明与评论中的内容不同。那将是mov si, ax
    同样重要的是,您不应该在程序的这一点上破坏SI

  • testposition 部分中的 dec ax 指令中,我们看到您希望 XY 是从 1 开始的坐标。没关系,但您必须在计算中使用 DHDL 中的本地修改值:

  • 偏移地址计算适合字节大小的数组(迷宫)。因此,您不应该从中比较一个单词

尝试下一个代码:

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

最后一个问题

你确定方向变量dir实际上是一个word。我希望在 byte 大小的变量中找到那个小值。

【讨论】:

  • 你是一个绝对的天使,非常感谢你的帮助。这已经让我死了好几天了,总的来说,我学到了很多东西,感谢你的帮助。
猜你喜欢
  • 2011-09-22
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 2010-12-01
  • 1970-01-01
  • 2015-12-05
  • 2014-04-09
相关资源
最近更新 更多