【问题标题】:fasm, searching a word in dos environmentfasm,在dos环境下搜索一个词
【发布时间】:2015-03-17 23:05:25
【问题描述】:

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

【问题讨论】:

  • 准确的完整错误信息是什么?
  • 保留字用作符号。
  • 您不能以dldx 为基础进行索引。您可以索引bpbx(指定的基址寄存器),因此请尝试使用xor bx,bxmov bl,dlmov dl,[bx+di]。有关详细信息,请参阅 Google“x86 寻址模式”。
  • 感谢您的回复。我用代码编辑了帖子上部。现在没有错误,但程序无法正常运行并且什么也没有显示。例如,以“comsp”开头的行不显示。如何解决?你有什么想法吗?
  • 它甚至没有写出“THE WORD:”?

标签: assembly dos fasm


【解决方案1】:

除了前面提到的 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

上面的 cmets 应该解释为什么你没有看到任何输出或者你的终端为什么会关闭(可能是dl 中的一些控制字符)。

mov di,$-word 中的表达式 $-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"

【讨论】:

  • as mov di,$-word 我想知道单词的长度。 :)
  • @csal 这不是单词的长度。 $ 代表“当前位置”,因此它实际上是该 mov 指令的地址。如果你想要单词的长度,你应该在word之后设置一个新的数据项,类似于word_length db $-word。这是因为$ 在这种情况下代表word_length 的地址。
【解决方案2】:

问题在于汇编语言的能力,更具体地说,在于处理器可以直接做什么。您尝试执行的间接内存引用无效,因为处理器不会直接添加索引寄存器 (di) 和通用寄存器 (dl) 作为指针取消引用操作(它确实允许di + 常量,就像你在下面做几行一样)。

错误消息(虽然有点混乱)来自dl 在该特定位置是一个无效寄存器这一事实。有效的选项可以是di/si+bx+constant,或者它们的任意组合。

一种可能的解决方法是使用bp 寄存器作为变量值的中间体,而不是dl,这在这种情况下的间接引用中是允许的。这样的事情至少可以解决这个错误:

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

请注意,由于bp 是 16 位宽而 dl 只有 8,我不得不丢弃高 8 位以保留先前的预期行为,and 指令通过将它们清零并保持其余部分不变来实现。

【讨论】:

  • 感谢您的解释,但我解决了这个问题。现在没有错误,但程序仍然无法正常运行。
  • 但是使用 BP 作为地址寄存器,如 [bp+di],那么 SS 寄存器是默认的段寄存器。如果我们想指向数据段或代码段,我们需要额外的段覆盖前缀 [ds:bp+di] 或 [cs:bp+di] 例如。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-14
  • 2018-03-17
  • 1970-01-01
  • 2016-07-15
相关资源
最近更新 更多