加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

assembly – 缓冲输入的工作原理

发布时间:2020-12-14 04:26:24 所属栏目:Windows 来源:网络整理
导读:下一个程序的输入工作正常,但是当我要求显示输出时,DOS ?根本不显示任何东西!这怎么可能? ORG 256 mov dx,msg1 mov ah,09h ;DOS.WriteString int 21h mov dx,buf mov ah,0Ah ;DOS.BufferedInput int 21h mov dx,msg2 mov ah,09h ;DOS.WriteString int 21h
下一个程序的输入工作正常,但是当我要求显示输出时,DOS
?根本不显示任何东西!这怎么可能?

ORG     256
        mov     dx,msg1
        mov     ah,09h                 ;DOS.WriteString
        int     21h
        mov     dx,buf
        mov     ah,0Ah                 ;DOS.BufferedInput
        int     21h
        mov     dx,msg2
        mov     ah,09h                 ;DOS.WriteString
        int     21h
        mov     ax,4C00h               ;DOS.TerminateWithExitcode
        int     21h
; --------------------------------------
msg1:   db      'Input : ','$'
buf:    db      20 dup ('$')
msg2:   db      13,10,'Output : ','$'
; --------------------------------------

解决方法

看看你如何定义你的输入缓冲区(buf:db 20 dup(‘$’)),我明白了
?你想要偷工减料并且输入已经为$-terminated准备好了
?重新显示它.遗憾的是,这会扰乱DOS输入所需的设置
?功能0Ah和您的程序遇到潜在缓冲区的严重问题
?超限.
此外,使用$-termination并不是您可以做出的最明智的选择
?因为$字符可能已经出现在输入的字符中.
?我在下面介绍的所有示例程序都将使用零终止
?代替.

使用int输入文本21h AH = 0Ah

这个Buffered STDIN Input函数从键盘获取字符
?继续这样做,直到用户按下Enter键.所有
?字符和最终回车符放在存储空间中
?从调用程序提供的输入缓冲区的第3个字节开始
?通过DS:DX中的指针.
不包括最终回车的字符数存储在
?输入缓冲区的第二个字节.
调用程序的责任是告诉DOS有多大
?存储空间是.因此,您必须将其长度放在第1个字节中
?调用此函数前输入缓冲区.允许输入1
?您将存储大小设置为2的字符.允许输入254
?您将存储大小设置为255的字符.
如果您不希望能够从模板中调用任何先前的输入,
?那么最好也将第二个字节归零.基本上模板是
?调用程序的输入缓冲区中预先存在的(和有效的)内容
?提供.如果预先存在的内容无效,则模板不是
?可用.

令人惊讶的是,此功能的编辑功能有限.

> Escape从当前输入中删除所有字符.
当前输入被放弃但保留在屏幕上并且光标被放置
输入首次开始的下一行.
> Backspace从当前输入中删除最后一个字符.
如果输入保持在屏幕上的单行内,则按预期工作.
另一方面,如果输入跨越多行,那么这个退格将会
停在屏幕的左边缘.从那时起将会有一个严重的问题
逻辑输入和视觉输入之间的差异,因为逻辑上
退出将继续,直到达到存储空间中的第一个位置!
> F6在当前输入中插入文件结尾字符(1Ah).
屏幕将显示“^ Z”.
> F7在当前输入中插入一个零字节.
屏幕将显示“^ @”.
> ctrlEnter转换到下一行(执行a
回车和换行),没有任何东西被添加到当前输入,你
不能回去.

还有更多编辑键可用.它们都让人想起EDLIN.EXE,
?古老的DOS行编辑器,它是每个前一行的文本编辑器
?成为构建下一行的模板.

> F1将模板中的一个字符复制到新行.
> F2 …将模板中的所有字符复制到新行,直到指定的字符.
> F3将模板中的所有剩余字符复制到新行.
> F4 …跳过模板中的字符
指定的字符.
> F5使新行成为新模板.
> Escape清除当前输入并保持模板不变.
>删除跳过模板中的一个字符.
>插入进入或退出插入模式.
> Backspace删除新行的最后一个字符,并将光标放回模板中的一个字符.
>左侧与Backspace相同.
>右边和F1一样.

选项卡由此功能扩展.标签扩展是替换的过程
ASCII 9由一系列一个或多个空格(ASCII 32)直到光标到达
?列位置是8的倍数.
此选项卡扩展仅在屏幕上发生.存储空间将保留ASCII 9.

这个函数执行ctrlC / ctrlBreak
?检查.

当此函数完成时,光标将位于最左侧的列中
?当前行.

例1,缓冲STDIN输入.

ORG     256                     ;Create .COM program
        cld
        mov     si,msg1
        call    WriteStringDOS
        mov     dx,0Ah                 ;DOS.BufferedInput
        int     21h
        mov     si,msg2
        call    WriteStringDOS
        mov     si,buf+2
        movzx   bx,[si-1]              ;Get character count
        mov     word [si+bx+1],10      ;Keep CR,append LF and 0
        call    WriteStringDOS
        mov     ax,4C00h               ;DOS.TerminateWithExitcode
        int     21h
; --------------------------------------
; IN (ds:si) OUT ()
WriteStringDOS:
        pusha
        jmps    .b
.a:     mov     dl,al
        mov     ah,02h                 ;DOS.DisplayCharacter
        int     21h                     ; -> AL
.b:     lodsb
        test    al,al
        jnz     .a
        popa
        ret
; --------------------------------------
buf:    db      255,16,"I'm the template",13,255-16-1+2 dup (0)
msg1:   db      'Choose color ? ',0
msg2:   db      10,'You chose ',0
; --------------------------------------

使用int 21h AH = 3Fh输入文本

当与预定义的句柄0(在BX中)一起使用时,这个Read From File Or Device
?函数从键盘获取字符并继续这样做,直到
?用户按Enter键.所有字符(从不超过127)和
?最后的回车加上额外的换行符放在私人中
?DOS内核中的缓冲区.这现在成为新模板.
此后该功能将写入DS:DX提供的缓冲区中的金额
?在CX参数中请求的字节数.如果CX指定了一个数字
?它小于此输入生成的一个或多个字节数
?需要额外调用此函数才能检索完整的输入.
?只要有剩余的字符被拿起,这个功能就会
?不使用键盘启动另一个输入会话!这之间甚至是如此
?同一计划的不同计划或会议.

可以使用上一节中描述的所有编辑键.

选项卡仅在屏幕上展开,而不在模板中展开.

这个函数执行ctrlC / ctrlBreak
?检查.

当此函数完成时,光标将位于最左侧的列中

>如果终止换行符不在返回的字节中,则为当前行.
>如果终止换行符在返回的字节中,则为下一行.

例2a,从文件或设备读取,一次全部拿起.

ORG     256                     ;Create .COM program
        cld
        mov     si,buf
        mov     cx,127+2               ;Max input is 127 chars + CR + LF
        xor     bx,bx                  ;STDIN=0
        mov     ah,3Fh                 ;DOS.ReadFileOrDevice
        int     21h                     ; -> AX CF
        jc      Exit
        mov     bx,ax                  ;Bytes count is less than CX
        mov     si,buf
        mov     [si+bx],bh             ;Keep CR and LF,append 0 (BH=0)
        call    WriteStringDOS
Exit:   mov     ax,al
        jnz     .a
        popa
        ret
; --------------------------------------
buf:    db      127+2+1 dup (0)
msg1:   db      'Choose color ? ',0
msg2:   db      'You chose ',0
; --------------------------------------

例2b,一次拾取一个字节.

ORG     256                     ;Create .COM program
        cld
        mov     si,1
        xor     bx,3Fh                 ;DOS.ReadFileOrDevice
        int     21h                     ; -> AX CF
        jc      Exit
        mov     si,dx                  ;DX=buf,CX=1,BX=0
Next:   mov     ah,3Fh                 ;DOS.ReadFileOrDevice
        int     21h                     ; -> AX CF
        jc      Exit
        call    WriteStringDOS          ;Display a single byte
        cmp     byte [si],10
        jne     Next
Exit:   mov     ax,al
        jnz     .a
        popa
        ret
; --------------------------------------
msg1:   db      'Choose color ? ','You chose '
buf:    db      0,0
; --------------------------------------

使用int 2Fh AX = 4810h输入文本

这个DOSKEY Buffered STDIN Input函数只能调用if the
DOSKEY.COM TSR was installed.它的运行方式与常规的Buffered非常相似
?STDIN输入功能0Ah(见上文),但具有相同的编辑功能
?作为DOS命令行的可能性,包括使用所有的能力
?DOSKEY特殊键.

> Up从历史记录中获取上一个项目.
> Down从历史记录中获取下一个项目.
> F7显示历史记录中所有项目的列表.
> AltF7清除历史记录.
> … F8查找以…开头的项目
> F9按编号从历史记录中选择项目.
> AltF10删除所有宏定义.

在DOS 6.2上,存储空间始终限制为128个字节,允许输入
?127个字符和强制回车的空间.不是
?可以预先加载模板,因此始终设置输入的第二个字节
?缓冲到零.
在DOS Win95上,如果安装了,则存储空间可以大到255个字节
?DOSKEY.COM TSR与doskey / line之类的命令:255.有可能
?使用模板预加载存储空间.这带来了Win95版本
?非常接近输入功能0Ah可行的.

这个函数执行ctrlC / ctrlBreak
?检查.

当此函数完成时,光标将位于最左侧的列中
?当前行.如果字符数为零,则表示用户输入了
?尚未展开的DOSKEY宏的名称.你没有
?去看看未展开的线!需要第二次调用该函数
?并且在这次返回时,光标将位于最后一个字符的后面
?扩展文本.
一个特点是当一个多命令宏($T)扩展时,你只是
?获取第一个命令的扩展文本.额外的调用
?获取其他扩展文本需要函数.虽然这一切都是
?在COMMAND.COM等命令shell中,从用户内部非常有用
?应用它真的很烦人,你不知道什么时候发生这种情况.

由于输入的文本被添加到命令历史中,因此不可避免
?历史填补了无关的项目.当然不是你想看到的
?在DOS提示符下!

例3,调用DOSKEY.COM.

ORG     256                     ;Create .COM program
        cld
        mov     ax,4800h               ;DOSKEY.CheckInstalled
        int     2Fh                     ; -> AL
        test    al,al
        mov     si,err1
        jz      Exit_
Again:  mov     si,buf
        mov     ax,4810h               ;DOSKEY.BufferedInput
        int     2Fh                     ; -> AX
        test    ax,ax
        mov     si,err2
        jnz     Exit_
        cmp     [buf+1],al             ;AL=0
        je      Again                   ;Macro expansion needed
        mov     si,[si-1]              ;Get character count (is GT 0)
        mov     word [si+bx+1],append LF and 0
Exit_:  call    WriteStringDOS
Exit:   mov     ax,al
        jnz     .a
        popa
        ret
; --------------------------------------
buf:    db      128,128+2 dup (0)
msg1:   db      'Choose color ? ',0
msg2:   db      13,0
err1:   db      'N/A',0
err2:   db      'Failed',0
; --------------------------------------

使用int 21h AH = 08h输入文本

Because of the 30000 byte limit that Stack Overflow imposes the text continues in the below answer…

问题理解源?我使用的汇编程序:

>将以点(.)开头的标签视为第一级本地标签>将以冒号(:)开头的标签视为第二级本地标签>是单指令多操作数(SIMO),所以推cx si转换为推送cx push si.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读