0

The exercise is to take a word from keyboard, search the DOS environment and if that word is there, display the line with this word from DOS environment.

Here is my code:

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,"$'            

The compiler says: mov dl,[dl+di] error. I am a begginer, how to fix the code? I have no idea.

  • What is the exact, full error message? – Alejandro Mar 17 '15 at 23:16
  • reserved word used as a symbole. –  Mar 17 '15 at 23:23
  • You can't index off of `dl` or `dx` as a base. You can index off of `bp` or `bx` (designated base registers), so try instead, `xor bx,bx`, `mov bl,dl`, `mov dl,[bx+di]`. For more information, Google "x86 addressing modes". – lurker Mar 17 '15 at 23:31
  • Thank you for your response. I edited the post upper with the code. Now there are no errors, but the program does not work properly and shows nothing. For example the line which starts with "comsp" does not display. How to fix it? Do you have any idea? –  Mar 17 '15 at 23:47
  • It doesn't even write out, "THE WORD:"? – lurker Mar 17 '15 at 23:59
  • It write out it, then I type "comsp", but after "enter" terminal switch off. –  Mar 18 '15 at 00:03
  • You didn't clear `bx` before `mov bl,dl` like I suggested. You'll get strange results if you don't. You need the `xor bx,bx` that I mentioned in my previous comment. – lurker Mar 18 '15 at 00:37

2 Answers2

0

Problem lies in the capabilities of assembly language, more specifically in what the processor can do directly. The indirect memory reference you're attempting to do is not valid, as the processor don't do the addition of an index register (di) and a general register (dl) directly as a pointer dereferencing operation (it does allow di + constant as you do a few lines below, though).

The error message (although a bit confusing) comes from the fact that dl is an invalid register in that particular place. Valid options could be di/si+bx+constant, or any combination of those.

A possible workaround could be to use the bp register as an intermediate for the variable value instead of dl, which is allowed in indirect references like this case. Something like this will fix this error at least:

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

Note that since bp is 16 bits wide and dl is only 8, I had to discard the 8 upper bits to preserve previous intended behavior, the and instruction does it by zeroing out those and leave the rest untouched.

Alejandro
  • 7,290
  • 4
  • 34
  • 59
  • Thank you for explanation, but I fixed that problem. There are now no errors, but the program still does not work properly. –  Mar 17 '15 at 23:58
  • But using BP as an addressregister like [bp+di] then the SS-register is the default segment-register. If we want to point into the data segment, or code segment, the we need additional a segment override prefix [ds:bp+di], or [cs:bp+di] for example. – Dirk Wolfgang Glomp Mar 18 '15 at 08:56
0

Aside from the issue previously mentioned with x86 base plus index addressing, here are some additional questions and problems, some of which are leading to your undesired results:

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

The above comments should explain why you aren't seeing any output or why your terminal switches off (perhaps some control character in dl).

The expression $-word in mov di,$-word is not the length of the word at word. The $ symbol represents the address of the current location in which the $ appears, so in the above, it's actually the address of that mov instruction. Therefore, you're getting some odd negative number in di than you wanted. If you want the length of the word, you should set a new data item after word, a common pattern is to make it an item after the definition of 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"
lurker
  • 56,987
  • 9
  • 69
  • 103
  • as mov di,$-word I wanted to let know the length of the word. :) –  Mar 18 '15 at 00:19
  • @csal that's not the length of the word. The `$` represents the "current location", so it's actually the address of that `mov` instruction. If you want the length of the word, you should set a new data item after `word` that is something like, `word_length db $-word`. That works because `$` in that case represents the address of `word_length`. – lurker Mar 18 '15 at 00:20