Фасм, поиск слова в 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 инструкция делает это, обнуляя их и оставляя нетронутыми остальные.

Другие вопросы по тегам