缓冲输入如何工作

2024-01-07

下一个程序中的输入(使用 DOS.BufferedInput 函数 0Ah)工作正常,但是当我要求显示输出时,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     dx, buf
        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 : ', '$'
; --------------------------------------

Notice这个自我回答的问答有一个由两部分组成的答案。任何有兴趣的人都应该从以下开始阅读accepted answer.


看看你如何定义你的输入缓冲区(buf: db 20 dup ('$')), 我得到它 您想要走捷径并准备好以 $ 结尾的输入 重新显示它。遗憾的是,这扰乱了 DOS 输入所需的设置 函数 0Ah 并且您的程序存在潜在缓冲区的严重问题 超支。
此外,使用 $ 终止并不是您可以做出的最明智的选择 因为 $ 字符可能已经出现在输入的字符中。 我在下面介绍的所有示例程序都将使用零终止 反而。

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

This Buffered STDIN Input http://www.ctyme.com/intr/rb-2563.htm function gets characters from the keyboard and continues doing so until the user presses the Enter key. All characters and the final carriage return are placed in the storage space that starts at the 3rd byte of the input buffer supplied by the calling program via the pointer in DS:DX.
The character count, not including the final carriage return, is stored in the 2nd byte of the input buffer.
It's the responsibility of the calling program to tell DOS how large the storage space is. Therefore you must put its length in the 1st byte of the input buffer before calling this function. To allow for an input of 1 character you set the storage size at 2. To allow for an input of 254 characters you set the storage size at 255.
If you don't want to be able to recall from the template any previous input, then it is best to also zero the 2nd byte. Basically the template is the pre-existing (and valid) content in the input buffer that the calling program provided. If pre-existing content is invalid then the template is not available.

令人惊讶的是,该功能的编辑功能有限。

  • Escape Removes all characters from the current input.
    The current input is abandoned but stays on screen and the cursor is placed on the next row, beneath where the input first started.
  • Backspace Removes the last character from the current input.
    Works as expected if the input stays within a single row on screen. If on the other hand the input spans several rows then this backspacing will stop at the left edge of the screen. From then on there will be a serious discrepancy between the logical input and the visual input because logically backspacing will go on until the 1st position in the storage space is reached!
  • F6 Inserts an end-of-file character (1Ah) in the current input.
    The screen will show "^Z".
  • F7 Inserts a zero byte in the current input.
    The screen will show "^@".
  • ctrlEnter Transitions to the next row (executing a carriage return and linefeed), nothing is added to the current input, and you can't go back.

还有更多编辑键可用。他们都让人想起埃德林程序, 古老的 DOS 行编辑器,它是一个文本编辑器,其中前面的每一行 成为您构建下一行的模板。

  • F1 Copies one character from the template to the new line.
  • F2 + ... Copies all characters from the template to the new line, up to the character specified.
  • F3 Copies all remaining characters in the template to the new line.
  • F4 + ... Skips over the characters in the template, up to the character specified.
  • F5 Makes the new line the new template.
  • Escape Clears the current input and leaves the template unchanged.
  • Delete Skips one character in the template.
  • Insert Enters or exits insert mode.
  • Backspace Deletes the last character of the new line and places the cursor back one character in the template.
  • Left Same as Backspace.
  • Right Same as F1.

通过此功能可以扩展选项卡。 Tab扩展就是替换的过程 ASCII 9 由一系列一个或多个空格 (ASCII 32) 组成,直到光标到达 8 的倍数的列位置。
此选项卡扩展仅发生在屏幕上。存储空间将保存 ASCII 9。

This function does ctrlC/ctrlBreak checking.

当该函数完成后,光标将位于屏幕最左侧的列中 当前行。

示例 1,缓冲 STDIN 输入。

        ORG     256                     ;Create .COM program
        cld
        mov     si, msg1
        call    WriteStringDOS
        mov     dx, buf
        mov     ah, 0Ah                 ;DOS.BufferedInput
        int     21h
        mov     si, msg2
        call    WriteStringDOS
        mov     si, buf+2
        movzx   bx, byte [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

When used with predefined handle 0 (in BX) this Read From File Or Device http://www.ctyme.com/intr/rb-2783.htm function gets characters from the keyboard and continues doing so until the user presses Enter. All characters (never more than 127) and the final carriage return plus an additional linefeed are placed in a private buffer within the DOS kernel. This now becomes the new template.
Hereafter the function will write in the buffer provided at DS:DX, the amount of bytes that were requested in the CX parameter. If CX specified a number that is less than the number of bytes generated by this input, one or more additional calls to this function are required to retrieve the complete input. As long as there are characters remaining to be picked up, this function will not launch another input session using the keyboard! This is even true between different programs or sessions of the same program.

上一节中描述的所有编辑键均可用。

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

This function does ctrlC/ctrlBreak checking.

当该函数完成后,光标将位于屏幕最左侧的列中

  • 如果终止换行不在返回的字节中,则返回当前行。
  • 如果终止换行符位于返回的字节中,则返回下一行。

示例 2a,从文件或设备读取,一次全部拾取。

        ORG     256                     ;Create .COM program
        cld
        mov     si, msg1
        call    WriteStringDOS
        mov     dx, 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, msg2
        call    WriteStringDOS
        mov     si, buf
        mov     [si+bx], bh             ;Keep CR and LF, append 0 (BH=0)
        call    WriteStringDOS
Exit:   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      127+2+1 dup (0)
msg1:   db      'Choose color ? ', 0
msg2:   db      'You chose ', 0
; --------------------------------------

示例 2b,从文件或设备读取,一次拾取一个字节。

        ORG     256                     ;Create .COM program
        cld
        mov     si, msg1
        call    WriteStringDOS
        mov     dx, buf
        mov     cx, 1
        xor     bx, bx                  ;STDIN=0
        mov     ah, 3Fh                 ;DOS.ReadFileOrDevice
        int     21h                     ; -> AX CF
        jc      Exit
        mov     si, msg2
        call    WriteStringDOS
        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, 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
; --------------------------------------
msg1:   db      'Choose color ? ', 0
msg2:   db      10, 'You chose '
buf:    db      0, 0
; --------------------------------------

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

This DOSKEY 缓冲 STDIN 输入 http://www.techhelpmanual.com/703-int_2fh_4810h__get_keyboard_input_with_doskey_editing.html函数只能被调用如果 DOSKEY.COM TSR 已安装 http://www.techhelpmanual.com/702-int_2fh_4800h__is_doskey_com_installed_.html。它的运行方式与常规的 Buffered 非常相似 STDIN 输入功能 0Ah(见上文),但具有所有相同的编辑功能 与 DOS 命令行一样的可能性,包括使用所有功能的能力 DOSKEY 特殊键。

  • Up Gets previous item from history.
  • Down Gets next item from history.
  • F7 Shows a list of all the items in the history.
  • AltF7 Clears the history.
  • ...F8 Finds item(s) that start with ...
  • F9 Selects an item from the history by number.
  • AltF10 Removes all macrodefinitions.

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

This function does ctrlC/ctrlBreak checking.

当该函数完成后,光标将位于屏幕最左侧的列中 当前行。如果字符数为零,则表示用户输入了 尚未扩展的 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, msg1
        call    WriteStringDOS
        mov     dx, 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, msg2
        call    WriteStringDOS
        mov     si, buf+2
        movzx   bx, byte [si-1]         ;Get character count (is GT 0)
        mov     word [si+bx+1], 10      ;Keep CR, append LF and 0
Exit_:  call    WriteStringDOS
Exit:   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      128, 0, 128+2 dup (0)
msg1:   db      'Choose color ? ', 0
msg2:   db      13, 10, 'You chose ', 0
err1:   db      'N/A', 13, 10, 0
err2:   db      'Failed', 13, 10, 0
; --------------------------------------

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

由于 Stack Overflow 施加了 30000 字节的限制,文本将在下面的答案中继续...

理解来源有问题吗?我使用的汇编器:

  • 考虑以点开头的标签 (.) 作为第一级本地标签
  • 考虑以冒号开头的标签 (:) 作为二级本地标签
  • 是单指令多操作数(SIMO),所以push cx si翻译为push cx push si.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

缓冲输入如何工作 的相关文章

  • FreePascal x64 上系统单元函数的汇编调用

    我有一些 Delphi 汇编代码 可以在 Win32 Win64 和 OSX 32 上编译并正常工作 XE2 但是 由于我需要它在 Linux 上工作 所以我一直在考虑编译它的 FPC 版本 到目前为止 Win32 64 Linux32 6
  • 如何使用 Bochs 运行汇编代码?

    我想使用 Bochs 作为 8086 模拟器 是否有捷径可寻 我想要的是类似 emu8086 的东西 http www emu8086 com http www emu8086 com 如果程序的初始部分适合 512 字节 并且您不介意将自
  • 32位PPC rlwinm指令

    我在理解上有点困难rlwinmPPC 汇编指令 旋转左字立即然后与掩码 我正在尝试反转函数的这一部分 rlwinm r3 r3 0 28 28 我已经知道什么了r3 is r3在本例中是一个 4 字节整数 但我不确定这条指令到底是什么rlw
  • 如何检查用户是否按下了某个键?

    在java中 我有一个程序需要连续检查用户是否按下了某个键 所以在伪代码中 就像 if isPressing w do somthing 在java中 你不检查是否按下了某个键 而是检查listen to KeyEvents 实现您的目标的
  • 添加冗余赋值可以在未经优化的情况下编译时加快代码速度

    我发现一个有趣的现象 include
  • TensorFlow:在训练时更改变量

    如果我将输入管道从 feed dict 更改为 tf data dataset 如何在每次迭代后的训练期间更改网络内参数的值 澄清一下 旧代码看起来像这样 Define Training Step model is some class t
  • conio.h 不包含 textcolor()?

    我一直在考虑在我用 C 编写的 DOS 程序中使用颜色 有人告诉我conio h有textcolor 函数 但是当我在代码中使用它时 编译器 链接器会向我抛出错误 说我对该函数有未定义的引用 Does conio h真的有这个功能还是有人告
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • 使用“表单控件”删除输入字段的轮廓

    我有一个输入字段 如下所示 在类名中我将其作为form control
  • 如何从 C++ 中的文件中读取双精度值

    如何从 C 中的文件中读取 double 值 对于整数 我知道您可以使用 getline 然后使用 atoi 但我没有找到双倍函数的数组 什么可用于读取双精度数或将 char 数组转换为双精度数 您可以使用流提取 std ifstream
  • 如何通过单击图像预览上的“x”从文件输入中删除图像?

    我目前有一个文件输入 一旦用户上传图像 就会显示图像预览 在图像预览上 有一个 x 可以从列表中删除图像预览 单击此 x 后 有什么方法可以从输入中的文件集中删除图像吗
  • Intel:序列化指令和分支预测

    英特尔架构开发人员手册 http www intel com content www us en architecture and technology 64 ia 32 architectures software developer v
  • 使用 Gas 生成与位置无关的代码 (-fPIC)

    我尝试在 x86 64 上创建共享库但失败 问题归结为以下代码 请不要介意 它没有多大意义 section data newline ascii n section text globl write newline type write n
  • CISC 机器 - 它们不只是将复杂指令转换为 RISC 吗?

    也许我在架构上存在误解 但如果机器有 比如说 乘法指令 该指令是否未转换为更小的指令 或者过于复杂以至于最终与等效的 RISC 指令具有相同的速度 乘法是一个不好的例子 它在两种体系结构中都是一条指令 将上面的 乘法 替换为 CISC 中更
  • 标志寄存器中保留/未定义位的用途是什么?

    在 Z80 8080 8085 和 8086 处理器的标志寄存器中 被记录为 保留 或 未定义 的位 1 3 5 的用途是什么 这些位未使用 也就是说 没有指令明确地将它们设置为任何值 设计人员认为 5 6 个标志就足够了 他们只是将标志寄
  • 从由空格分隔的单个输入整数列表创建二维数组

    我正在解决一些问题geeksforgeeks我遇到了一个特定的问题 其中在测试用例中提供了输入 如下所示 2 2 denotes row column of the matrix 1 0 0 0 all the elements of th
  • MD 和 MKDIR 批处理命令有什么区别?

    这两个命令都会创建文件夹 我read http www computerhope com mdhlp htmMKDIR 甚至可以创建子文件夹 这只是区别吗 为什么有两个命令做同样的事情 我应该使用哪一个 除了 npocmaka 的answe
  • 使用
    元素作为 JavaScript 代码的输入。这是最好的方法吗?

    各位 显然 我是编码新手 所以最近完成了一些有关 HTML 和 Javascript 的 Lynda 课程后 我的简单 HTML 页面遇到了困难 基本上 我想要的是使用 JavaScript 进行基本计算 让用户使用 HTML 输入两个数字
  • 无法在 64 位 Linux 上从汇编 (yasm) 代码调用 C 标准库函数

    我有一个函数foo以汇编语言编写 并在 Linux Ubuntu 64 位上使用 yasm 和 GCC 编译 它只是使用以下命令将消息打印到标准输出puts 如下所示 bits 64 extern puts global foo secti

随机推荐

  • Google Chrome 防止捏合缩放

    我正在运行 Windows 8 1 的 Microsoft Surface Pro 2 上开发 Chrome 应用程序 最近 Chromium 团队决定在 Windows 8 的 Chrome 中添加捏合缩放手势 这一切都很好 然而 他们并
  • 需要通过CSS将网页中的图像居中

    即使调整浏览器大小 我也希望将图像在页面中垂直和水平居中 目前 我使用这个CSS centeredImage position fixed top 50 left 50 margin top 50px margin left 150px 还
  • 如何仅在尚未安装 .NET Framework 时安装它?

    有没有办法检查 NET Framework 4是否已安装并仅在系统中没有时才安装 我知道 如何通过检查以下注册表项来确定是否安装了 NET Framework 4 hasDotnet4 RegKeyExists HKEY LOCAL MAC
  • WKWebView 中的 Javascript - 评估 JavaScript 与 addUserScript

    我试图了解使用 WKWebview 执行 javascript 的最佳方式 有人可以给我使用 WKWebView 时的用例 最佳实践吗 何时使用添加用户脚本 and WKScript消息处理程序以及何时使用评估JavaScript let
  • 如何将数据播种到 Firebase Firestore?

    我有一个名为 Seed js 的文件 代码如下 我想将其数据从我的 React js 应用程序添加到 Firebase Firestore 有没有一个脚本可以让我做到这一点 想如果我包括 import seedDatabase from s
  • 在 Tensorflow 中添加整个训练/测试数据集的准确性摘要

    我正在尝试使用 Tensorboard 来可视化我的训练过程 我的目的是 当每个 epoch 完成时 我想使用整个验证数据集测试网络的准确性 并将此准确性结果存储到摘要文件中 以便我可以在 Tensorboard 中可视化它 我知道 Ten
  • 在 ggplot aes 中使用闪亮的输入值

    我正在尝试在 Shiny 中实现这 3 行代码 这是我想要的输出 install packages ggalt library ggalt health lt read csv https raw githubusercontent com
  • iOS 中的收据验证在沙箱测试期间返回不正确的信息

    我正在为我的应用程序实施收据验证 因为它是付费的 并且在以后的应用程序内购买中将是免费的 我已经设置了我的服务器和一切 并且我已经发送了收据数据 但是 当我收到响应时 无论如何 响应 JSON 总是显示original applicatio
  • 如何在绘图中添加多个带有循环的形状

    我使用plotly包在python中显示动态财务图表 然而 我没能用 for 循环将所有关键点线放在一张图表上 这是我的代码 fig update layout for i in range 0 len data shapes go lay
  • 如何防止IE10中滚动条覆盖内容?

    在 IE10 中 滚动条并不总是存在 当它出现时 它会作为覆盖层出现 这是一个很酷的功能 但我想为我的特定网站关闭它 因为它是一个全屏应用程序 而且我的徽标和菜单消失在其后面 IE10 CHROME 有人知道在 IE10 上始终将滚动条固定
  • 如何在我的共享 Hostgator 上创建 git 存储库?

    如何在我的共享 Hostgator 上创建 git 存储库 顺便获得了 SSH 访问权限 假设已经安装了 Git git init bare path to repo 如果未安装 Git 您将无法直接推送到托管存储库 但您可以通过执行以下操
  • 如何格式化/着色 NSTextView 字符串的技术

    我正在寻找一种可靠的技术来在 NSTextView 中进行简单的字符串格式化 粗体 斜体 文本解析几乎是用正则表达式完成的 但现在我需要应用字体特征并更改大小 关于如何将文本设为粗体的一些代码片段 textView textStorage
  • R:尽管“append = TRUE”,但当表存在时,为什么 dbWriteTable 会失败

    我正在尝试使用以下命令将新数据附加到已存在的 MySQL 表中dbWriteTable方法 我过去使用它没有问题 但现在失败了 因为表已经存在 这是尽管使用overwrite FALSE append TRUE 代码 full sum ta
  • 日食 | Packge 变成一个目录,破坏了我的整个项目

    所以我遇到的问题非常奇怪 当我设置了一个预先存在的项目 并将其从计算机 A 移动到计算机 B 时 我创建一个新项目并以正常方式导入它 它非常非常基于包 大约有 30 40 个包 将两个包制作成目录而不是包 例如 它不是 org projec
  • 为什么构造函数不能被显式调用,而析构函数却可以?

    在下面的 C 代码中 我可以显式调用析构函数 但不能显式调用构造函数 这是为什么 不会是明确的 ctor 调用更多富有表现力的 and unified与 dtor 案有关吗 class X int main X x X operator n
  • Key存在时出现KeyError

    使用 python 和 twitter api 获取 tweet 对象 我有一个包含推文的文件 tweetfile 我的计算机上的 txt 文件 我试图循环遍历对象以获取文本 我使用 tweetObj keys 检查了 twitter 对象
  • 使用nodemailer发送电子邮件

    我正在尝试使用 nodemailer 从我的应用程序发送电子邮件 我的设置如下 var nodemailer require nodemailer var smtpTransport require nodemailer smtp tran
  • 无法通过 ADB 连接到我的 Android 设备

    抱歉问了这个菜鸟问题 我在使用网络解决这个问题时遇到了麻烦 我试图通过 adb 将我的设备连接到我的电脑来调试我的应用程序 我的设备已植根 Adb 调试已启用 我下载了一个 adb 运行应用程序并启动了 ADB 现在我正在尝试 adb co
  • sched_getcpu() 相当于 OS X 吗?

    在 OS X 上 有没有办法找出线程正在哪个 CPU 上运行 Linux 的等效函数是调度获取CPU http man7 org linux man pages man3 sched getcpu 3 html 获取当前处理器编号 http
  • 缓冲输入如何工作

    下一个程序中的输入 使用 DOS BufferedInput 函数 0Ah 工作正常 但是当我要求显示输出时 DOS 根本不显示任何内容 这怎么可能 ORG 256 mov dx msg1 mov ah 09h DOS WriteStrin