Assembly 使用偏移量计算程序集从迷宫中获取字节
对于这个项目,我得到了一个迷宫,表示为一个字节数组,包含20h(可以移动到的空白空间)或任何其他内容(不能移动到的完整空间) 从驱动程序中,我得到了Assembly 使用偏移量计算程序集从迷宫中获取字节,assembly,masm,8086,Assembly,Masm,8086,对于这个项目,我得到了一个迷宫,表示为一个字节数组,包含20h(可以移动到的空白空间)或任何其他内容(不能移动到的完整空间) 从驱动程序中,我得到了 x pointer si y pointer di dir pointer bx E=1 S=2 W=3 N=4 maze pointer bp 一旦我确定一个空间是否为空,并且计算了我正在测试的字节所在的迷宫中的偏移量,我就知道了如何修改寄存器 公式:(Y-1)*30+(X-1)计算我要测试到数组中的字节的偏移量
x pointer si
y pointer di
dir pointer bx E=1 S=2 W=3 N=4
maze pointer bp
一旦我确定一个空间是否为空,并且计算了我正在测试的字节所在的迷宫中的偏移量,我就知道了如何修改寄存器
公式:(Y-1)*30+(X-1)计算我要测试到数组中的字节的偏移量。30是迷宫的宽度
所以本质上我需要做一些事情
mov al,ds:[bp+((Y-1)*30+(X-1))]
然后将迷宫中存储在al中的字节与20h进行比较,看我是否可以移动到那个位置
我目前的代码是:哪个工作正常
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
我们根据效率进行评分,并指出我们可以使用“高级间接寻址”来避免在ax中进行所有这些偏移量计算,因此如果您知道如何进行,我将不胜感激
以下是完整的代码:
;---------------------------------------------------------------------
; 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
下一个代码片段删去了一些指令
- 知道迷宫的宽度是30,我们就可以不用从内存中检索该值
- 我们可以在
指令的位移字段中隐藏从1基到0基的转换CMP
- 我们可以避免
和push
,并且仍然保留pop
寄存器SI
下一个代码片段删去了一些指令
- 知道迷宫的宽度是30,我们就可以不用从内存中检索该值
- 我们可以在
指令的位移字段中隐藏从1基到0基的转换CMP
- 我们可以避免
和push
,并且仍然保留pop
寄存器SI
表查找的替代方法:30是
32-2
。8086位移位不大(每个计数IIRC 1个周期),但(表查找的替代方法:30是32-2
。8086位移位不大(每个计数IIRC 1个周期),但(x
mov al, 30
mul dl <<< AX is too high by 30
add al, dh
adc ah, 0 <<< AX is too high by 30 + 1
xchg si, ax ; Preserve SI and load index
cmp byte ptr ds:[bp + si - 31], 20h
mov si, ax ; Restore SI
jne testnext
list dw 0, 30, 60, 90, 120, ...
^ ^
| | if Y=2
| if Y==1