练习是从键盘上取一个单词,搜索DOS环境,如果那个单词在那里,用DOS环境显示这个单词的行。
这是我的代码:
format binary
org 100h
start:
mov es,[ds:02ch]
xor si,si
;*****************************
;*****************************
mov ah,9
mov dx,string
int 21h
mov ah,10
mov dx,word
int 21h
mov ah,0
int 16h
;*****************************
;*****************************
xor di,di
xor bx,bx
start_while:
mov di,$-word
jge equal
mov dl,[es:si]
mov bl,dl
mov dl,[bx+di]
cmp dl,[string+di]
jne next_line
add di,1
jmp start_while
next_line:
inc si
cmp dl,0
jnz notexist
equal:
mov ah,2
int 21h
jmp end
notexist:
mov ah,9
mov dx,d_exist
int 21h
jmp end
end:
mov ah,08h
int 21h
ret
;**************************************
;**************************************
string db 'THE WORD:',10,13,"$"
word db 6
db 0
times 22 db "$"
d_exist db 'variable does not exist',10,13,"$'
编译器说:mov dl,[dl + di]错误。 我是一个初学者,如何修复代码?我不知道。
答案 0 :(得分:0)
问题在于汇编语言的功能,更具体地说在于处理器可以直接执行的操作。您尝试执行的间接内存引用无效,因为处理器不直接添加索引寄存器(di
)和通用寄存器(dl
)作为一个指针解除引用操作(它确实允许di
+不变,因为你在下面做了几行。)
错误消息(虽然有点令人困惑)来自dl
在该特定位置的无效寄存器这一事实。有效选项可以是di
/ si
+ bx
+常量,也可以是这些选项的任意组合。
可能的解决方法可能是使用bp
寄存器作为变量值的中间值而不是dl
,这在这种情况下的间接引用中是允许的。这样的事情至少会解决这个错误:
mov bp,[es:si]
and bp, 0x00ff
mov dl,[bp+di]
注意,由于bp
是16位宽且dl只有8,我不得不丢弃8位高位以保留先前的预期行为,and
指令通过将其归零并离开其余部分未受影响。
答案 1 :(得分:0)
除了前面提到的x86 base plus index寻址的问题之外,还有一些其他的问题和问题,其中一些会导致你的不良结果:
start:
mov es,[ds:02ch]
xor si,si
mov ah,9 ; Writes out THE WORD:
mov dx,string
int 21h
mov ah,10 ; Accepts user input into "word"
mov dx,word
int 21h ; reads buffered input for "word"
; reads keyboard key
; -->**** WHY? Input was just read above with INT 21 / AH = 10
;
mov ah,0
int 16h ; AH = scan code, AX = ASCII char
xor di,di
xor bx,bx
start_while:
mov di,$-word ; Moves address of current location
; minus address of "word" to di -->***WHY?
; The last operation to affect flags was xor bx,bx, which results
; in a zero. So this jump will ALWAYS be taken
jge equal
... All the code here up until the 'equal' label is skipped
equal:
mov ah,2 ; write the character in dl to stdout
; -->*** BUT the contents of dl are unknown
int 21h
jmp end ; exit the program
以上评论应解释为什么您没有看到任何输出或终端关闭的原因(可能是dl
中的某个控制字符)。
$-word
中的mov di,$-word
表达式不 word
处单词的长度。 $
符号表示$
出现的当前位置的地址,因此在上文中,它实际上是mov
的地址指令。因此,您在di
中得到的奇数为负数而不是您想要的。如果你想要单词的长度,你应该在word
之后设置一个新的数据项,一个常见的模式是使它成为word
定义之后的一个项目:
word db 6 ; This defines one byte, value = 6
db 0
times 22 db "$"
word_len db $-word ; Word length is current address - addr of "word"
; I'm assuming all 24 bytes above are for "word"