【问题标题】:Getting string input and displaying input with DOS interrupts MASM使用 DOS 中断 MASM 获取字符串输入和显示输入
【发布时间】:2015-06-12 19:30:39
【问题描述】:

在 MASM 中,我创建了一个缓冲区变量来保存从键盘输入的用户字符串。我被困在如何将字符串输入保存到该缓冲区变量中。我没有像 irvine 那样链接的任何库,并且希望通过 DOS 中断来执行此操作。到目前为止,我有一些类似的东西

            .model small

            .stack 100h

            .data
buff        db  25 dup(0), 10, 13
lbuff       EQU ($ - buff)              ; bytes in a string

            .code
main:
            mov ax, @data
            mov ds, ax              

            mov ah, 0Ah         ; doesn't work
            mov buff, ah        ; doesn't seem right
            int 21h                 


            mov     ax, 4000h       ; display to screen
            mov     bx, 1           
            mov     cx, lbuff           
            mov     dx, OFFSET buff     
            int     21h 

            mov ah, 4ch
            int 21h

            end main

我假设使用 0Ah 是正确的,因为它用于读取缓冲字符的输入数组。

【问题讨论】:

  • int 21h/0Ah 需要dx 中的缓冲区地址。缓冲区中的第一个字节需要是最大输入。通过在其中填充ah,您已经说过您想要十个字符(可能想要更多)。中断返回后,第二个字节为实际输入的字符数。输入文本从缓冲区 + 2 开始。
  • @FrankKotler 好的,所以我通过 mov dx, offset 25 mov ah, 0Ah int 21h 部分让它工作(对不起,我不确定如何在 cmets 中格式化它)。那么输入的字符是从 dx + 2 开始的吗?我如何将它移到我的 buff 变量中?
  • 输入函数需要在dx寄存器中缓冲区的开始“mov dx, OFFSET buff”和缓冲区第一个字节的最大输入,例如“mov [buff], ah”十个字符。输出函数需要“mov dx,OFFSET buff+2”和实际输入的字符数“mov cl,[buff+1]”。
  • @DirkWolfgangGlomp 所以应该是 mov dx, OFFSET buff 而不是 mov dx, OFFSET buff+2,因为字符串开始超过 2 个字节。然后mov cx, lbuff 需要变为mov cl, [buff+1],因为这将在字符串移位+2 后为您提供正确的字符串长度,对吗?那么我会在哪里做mov [buff], ah?就在mov ah, 0Ah之前?

标签: string assembly input keyboard masm


【解决方案1】:

我对您的代码进行了一些更改。首先,“buff”变量需要三级格式(允许的最大字符数、输入字符数的另一个字节以及缓冲区本身),因为这是服务 0AH 所需要的。为了使用服务 0AH,我添加了“offset buff”(正如 Wolfgang 所说)。这里是:

            .model small

            .stack 100h

            .data

buff        db  26        ;MAX NUMBER OF CHARACTERS ALLOWED (25).
            db  ?         ;NUMBER OF CHARACTERS ENTERED BY USER.
            db  26 dup(0) ;CHARACTERS ENTERED BY USER.

            .code
main:
            mov ax, @data
            mov ds, ax              

;CAPTURE STRING FROM KEYBOARD.                                    
            mov ah, 0Ah ;SERVICE TO CAPTURE STRING FROM KEYBOARD.
            mov dx, offset buff
            int 21h                 

;CHANGE CHR(13) BY '$'.
            mov si, offset buff + 1 ;NUMBER OF CHARACTERS ENTERED.
            mov cl, [ si ] ;MOVE LENGTH TO CL.
            mov ch, 0      ;CLEAR CH TO USE CX. 
            inc cx ;TO REACH CHR(13).
            add si, cx ;NOW SI POINTS TO CHR(13).
            mov al, '$'
            mov [ si ], al ;REPLACE CHR(13) BY '$'.            

;DISPLAY STRING.                   
            mov ah, 9 ;SERVICE TO DISPLAY STRING.
            mov dx, offset buff + 2 ;MUST END WITH '$'.
            int 21h

            mov ah, 4ch
            int 21h

            end main

当0AH从键盘捕获字符串时,它以ENTER(字符13)结束,这就是为什么如果要捕获25个字符,则必须指定26。

要知道用户输入了多少个字符(长度),请访问第二个字节(偏移量 buff + 1)。不包括 ENTER,因此,如果用户键入 8 个字符并 ENTER,则第二个字节将包含数字 8,而不是 9。

输入的字符从偏移量 buff + 2 开始,到字符 13 出现时结束。我们使用它来将长度添加到 buff+2 + 1 以将 chr(13) 替换为 '$'。现在我们可以显示字符串了。

【讨论】:

  • 是的:这 3 行代码都在 buff 变量中。是的:如果你想修改字符串中的字符,你必须让SI指向buff+2。
  • 使用 09h 函数来使用 40h 或 4000h 会不会更容易(我不确定为什么要使用 4000h,它是我的参考资料的一部分),这样它就不必在字符串的末尾有一个'$'?我能说的缺点是,即使用户没有输入完整的 25 个字符,它也会显示所有 25 个字符。
  • 如果你知道长度,你可以使用 ah=13h 和 int 10h(就像这个答案stackoverflow.com/questions/29460318/…),但是,如果你不想关心长度,你可以使用 $ .我从未尝试过 40 小时或 4000 小时。
  • @JoseManuelAbarcaRodriguez 您不必执行将 $ 放在 CH(13) 的 22 到 29 的步骤。你可以简单地用这个db 26 dup('$')替换db 26 dup(0)
【解决方案2】:

这是我的代码,也许可以帮到你。

;Input String Copy output

dataarea segment
    BUFFER db 81
           db ?
    STRING DB 81 DUP(?)
    STR1 DB 10,13,'$'   
dataarea ends

extra segment
    MESS1 DB 'After Copy',10,13,'$'
    MESS2 DB 81 DUP(?)
extra ends

code segment
main proc far
    assume cs:code,ds:dataarea,es:extra
start:
    push ds
    sub ax,ax
    push ax

    mov ax,dataarea   
    mov ds,ax

    mov ax,extra      
    mov es,ax

    lea dx,BUFFER     
    mov ah,0ah
    int 21h

    lea si,STRING
    lea di,MESS2
    mov ch,0
    mov cl,BUFFER+1
    cld
    rep movsb
    mov al,'$'
    mov es:[di],al

    lea dx,STR1            ;to next line
    mov ah,09h
    int 21h

    push es
    pop ds

    lea dx,MESS1           ;output:after copy
    mov ah,09h
    int 21h

    lea dx,MESS2
    mov ah,09h
    int 21h

    ret
main endp
code ends
    end start

结果是:

c:\demo.exe
Hello World!
After Copy
Hello World!

【讨论】:

    【解决方案3】:

    您可以按照以下代码:

    ; Problem : input array from user
    
    .MODEL SMALL
    .STACK
    .DATA
       ARR DB 10 DUB (?)     
    
    .CODE
     MAIN PROC
        MOV AX, @DATA
        MOV DS, AX
    
        XOR BX, BX
        MOV CX, 5
    
        FOR: 
          MOV AH, 1
          INT 21H
          MOV ARR[BX], AL
          INC BX
        LOOP FOR
    
        XOR BX, BX
        MOV CX, 5
    
        PRINT:  
         MOV AX, ARR[BX] ;point to the  current index 
    
         MOV AH, 2       ;output
         MOV DL, AX  
         INT 21H     
    
         INC BX           ;move pointer to the next element 
        LOOP PRINT       ;loop until done
    
     MAIN ENDP
    

    【讨论】:

      【解决方案4】:

      ;试试这个,它接受用户输入的10个字符的字符串,并以这种方式显示出来,“你好*10个字符的字符串输入”

      .MODEL TINY
      .CODE
      .286
      ORG 100h
      
          START:
           MOV DX, OFFSET BUFFER
           MOV AH, 0ah
           INT 21h
           JMP PRINT
           BUFFER DB 10,?, 10 dup(' ')
      
           PRINT:
           MOV AH, 02
           MOV DL, 0ah
           INT 21h
           MOV AH, 9
           MOV DX, OFFSET M1
           INT 21h
           XOR BX, BX
           MOV BL, BUFFER[1]
           MOV BUFFER [BX+2], '$'
           MOV DX, OFFSET BUFFER +2
           MOV AH, 9
           INT 21h
      
          M1: db 'Hello $'
      
      
       END START
       END      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-22
        • 1970-01-01
        • 2012-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多