如何从 DOS 中的标准输入中读取字符以便重定向有效?
How to read a character from standard input in DOS such that redirection works?
我目前正在编写DOS程序。在这个程序中,我使用服务 21/AH=01 从标准输入中读取一个字符。但是,当我从文件重定向标准输入时,EOF 检测似乎没有按预期工作。我用 nasm 语法编写了这个示例程序来说明问题:
org 0x100
; read characters and sum them up
main: xor bx,bx
.1: mov ah,1
int 0x21
xor ah,ah
add bx,ax
cmp al,0x1a ; eof reached?
jnz .1
mov cx,4
.2: mov si,bx
shr si,12
mov dl,[hextab+si] ; convert to hex
mov ah,2
int 0x21
shl bx,4
loop .2
ret
hextab: db '0123456789ABCDEF'
当我从文件重定向标准输入时,程序挂起,除非该文件在某处包含 ^Z。我的印象是 EOF 被标记为服务 21/AH=01 在 DOS 中返回 ^Z,但是,情况似乎并非如此。
如何在 DOS 中以与重定向标准输入一起工作的方式从标准输入中读取字符,以便在输入未重定向的情况下将字符回显到屏幕上,以便我可以检测到 EOF 条件?理想情况下,我想要一些行为类似于 getchar()
函数的东西。
您应该改用 MS-DOS "read" 函数。通常,您希望避免使用旧的、过时的 MS-DOS 1.x API 函数。输出函数(AH=1,AH=9)通常是可以的,但其余大部分不应该使用,除非你的程序需要在 MS-DOS 1 下 运行。MS-DOS 2.0 引入了一个整体一组新的类 Unix 文件函数,大部分工作就像等效的 Unix 函数。所以在这种情况下,MS-DOS 读取函数就像 Unix read
系统调用一样,需要三个参数:文件句柄、缓冲区地址和要读取的字符数。与 Unix 一样,文件句柄 0 用于标准输入,1 用于标准输出,2 用于标准错误。
因此您可以重写示例以使用 MS-DOS 读取 (AH=3Fh) 和写入 (AH=40h) 函数,如下所示:
ORG 0x100
main:
xor di, di
mov bp, buf
mov dx, bp
mov cx, 1
loopchar:
mov ah, 0x3f
int 21h
jc error
dec ax
js eof ; EOF reached?
cmp BYTE [bp], 0x1a
je eof
add di, [bp]
jmp loopchar
eof:
inc cx
mov ax, di
mov al, ah
call printhex1
jc error
xchg ax, di
printhex1:
mov bx, hextab
aam 16
xlat
mov [bp + 1], al
mov al, ah
xlat
mov [bp], al
mov bx, 1
mov ah, 0x40
int 21h
error:
ret
buf db 0, 0
hextab: db '0123456789ABCDEF'
我目前正在编写DOS程序。在这个程序中,我使用服务 21/AH=01 从标准输入中读取一个字符。但是,当我从文件重定向标准输入时,EOF 检测似乎没有按预期工作。我用 nasm 语法编写了这个示例程序来说明问题:
org 0x100
; read characters and sum them up
main: xor bx,bx
.1: mov ah,1
int 0x21
xor ah,ah
add bx,ax
cmp al,0x1a ; eof reached?
jnz .1
mov cx,4
.2: mov si,bx
shr si,12
mov dl,[hextab+si] ; convert to hex
mov ah,2
int 0x21
shl bx,4
loop .2
ret
hextab: db '0123456789ABCDEF'
当我从文件重定向标准输入时,程序挂起,除非该文件在某处包含 ^Z。我的印象是 EOF 被标记为服务 21/AH=01 在 DOS 中返回 ^Z,但是,情况似乎并非如此。
如何在 DOS 中以与重定向标准输入一起工作的方式从标准输入中读取字符,以便在输入未重定向的情况下将字符回显到屏幕上,以便我可以检测到 EOF 条件?理想情况下,我想要一些行为类似于 getchar()
函数的东西。
您应该改用 MS-DOS "read" 函数。通常,您希望避免使用旧的、过时的 MS-DOS 1.x API 函数。输出函数(AH=1,AH=9)通常是可以的,但其余大部分不应该使用,除非你的程序需要在 MS-DOS 1 下 运行。MS-DOS 2.0 引入了一个整体一组新的类 Unix 文件函数,大部分工作就像等效的 Unix 函数。所以在这种情况下,MS-DOS 读取函数就像 Unix read
系统调用一样,需要三个参数:文件句柄、缓冲区地址和要读取的字符数。与 Unix 一样,文件句柄 0 用于标准输入,1 用于标准输出,2 用于标准错误。
因此您可以重写示例以使用 MS-DOS 读取 (AH=3Fh) 和写入 (AH=40h) 函数,如下所示:
ORG 0x100
main:
xor di, di
mov bp, buf
mov dx, bp
mov cx, 1
loopchar:
mov ah, 0x3f
int 21h
jc error
dec ax
js eof ; EOF reached?
cmp BYTE [bp], 0x1a
je eof
add di, [bp]
jmp loopchar
eof:
inc cx
mov ax, di
mov al, ah
call printhex1
jc error
xchg ax, di
printhex1:
mov bx, hextab
aam 16
xlat
mov [bp + 1], al
mov al, ah
xlat
mov [bp], al
mov bx, 1
mov ah, 0x40
int 21h
error:
ret
buf db 0, 0
hextab: db '0123456789ABCDEF'