Фасм, поиск слова в DOS среде
Упражнение состоит в том, чтобы взять слово с клавиатуры, выполнить поиск в среде 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] error. Я начинающий, как исправить код? Я понятия не имею.
2 ответа
Помимо проблемы, упомянутой ранее с адресацией 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"
Проблема заключается в возможностях ассемблера, а точнее в том, что процессор может делать напрямую. Ссылка на косвенную память, которую вы пытаетесь сделать, недопустима, так как процессор не добавляет регистр индекса (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
инструкция делает это, обнуляя их и оставляя нетронутыми остальные.