如何从DOS中的标准输入读取字符,以便重定向工作?

时间:2017-06-03 23:17:41

标签: assembly stdin dos x86-16 io-redirection

我目前正在编写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,但是,似乎并非如此。

如何以与重定向的stdin一起使用的方式从DOS中的标准输入读取字符,以便在未重定向输入的情况下将字符回显到屏幕,以便我可以检测到EOF条件?理想情况下,我希望有一些行为类似于getchar()函数。

1 个答案:

答案 0 :(得分:6)

您应该使用MS-DOS“读取”功能。通常,您希望避免旧的过时的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'