在dos环境中搜索一个单词

时间:2015-03-17 23:05:25

标签: assembly dos fasm

练习是从键盘上取一个单词,搜索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]错误。 我是一个初学者,如何修复代码?我不知道。

2 个答案:

答案 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"