看看你如何定义你的输入缓冲区(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
.