2015-03-17 3 views
0

Упражнение - взять слово с клавиатуры, искать среду DOS, и если это слово есть, отобразите строку с этим словом из среды DOS.fasm, поиск слова в среде 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,"$'    

Компилятор говорит: мов дл, [дл + ди] ошибка. Я начинаю, как исправить код? Понятия не имею.

+0

Что такое точное, полное сообщение об ошибке? – Alejandro

+0

зарезервированное слово используется как символ. –

+0

Вы не можете индексировать данные 'dl' или' dx' в качестве базы. Вы можете индексировать «bp» или «bx» (обозначенные базовые регистры), поэтому вместо этого попробуйте «xor bx, bx',» mov bl, dl', 'mov dl, [bx + di]'. Для получения дополнительной информации, «Режимы адресации x86» в Google. – lurker

ответ

0

Помимо вопроса упоминалось ранее с x86 база плюс индекс адресации, вот некоторые дополнительные вопросы и проблемы, некоторые из которых являются ведущие к нежелательным результатам:

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" 
+0

as mov di, $ - word Я хотел сообщить длину слова. :) –

+0

@csal, это не длина слова. «$» Представляет «текущее местоположение», поэтому на самом деле это адрес этой команды «mov». Если вам нужна длина слова, вы должны установить новый элемент данных после слова «word», что-то вроде «word_length db $ -word». Это работает, потому что '$' в этом случае представляет адрес 'word_length'. – lurker

0

Проблема заключается в возможностях языка ассемблера, а конкретно в том, что процессор может делать напрямую. Ссылка на косвенную память, которую вы пытаетесь сделать, недопустима, так как процессор не добавляет индексный регистр (di) и общий регистр (dl) непосредственно как операция разыменования указателя (она позволяет di + константа как вы делаете несколько строк ниже, хотя).

Сообщение об ошибке (хотя и немного запутанное) связано с тем, что dl является недопустимым регистром в этом конкретном месте. Допустимыми параметрами могут быть di/si + bx + константа или любая их комбинация.

Возможным обходным решением может быть использование регистра bp в качестве промежуточного значения для значения переменной вместо dl, что допускается в косвенных ссылках, подобных этому случаю. Что-то, как это будет исправить эту ошибку, по крайней мере:

mov bp,[es:si] 
and bp, 0x00ff 
mov dl,[bp+di] 

Обратите внимание, что поскольку bp имеет ширину 16 бита и дли только 8, я должен был отказаться от 8 старших бит, чтобы сохранить предыдущее намеченное поведение, то and инструкция делает это путем обнуления их и оставления остальных нетронутыми.

+0

Спасибо за объяснение, но я исправил эту проблему. В настоящее время ошибок нет, но программа по-прежнему работает неправильно. –

+0

Но используя BP в качестве адресного регистра, например [bp + di], SS-регистр является регистром сегмента по умолчанию. Если мы хотим указать в сегмент данных или сегмент кода, нам нужен дополнительный префикс переопределения сегмента [ds: bp + di] или [cs: bp + di], например. –

 Смежные вопросы

  • Нет связанных вопросов^_^