2017-06-03 36 views
3

我目前正在編寫一個DOS程序。在這個程序中,我使用服務21/AH=01從標準輸入中讀取一個字符。但是,似乎在從文件重定向標準輸入時,EOF檢測無法按預期工作。我在NASM語法寫了這個示例程序來說明這個問題:如何從DOS中的標準輸入中讀取字符,以便重定向起作用?

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 'ABCDEF' 

當我從一個文件重定向標準輸入,程序掛起,除非該文件包含了^ Z地方。我的印象是EOF在服務器21/AH = 01上標記爲返回^ Z,但是,似乎並非如此。

如何從DOS中的標準輸入中讀取一個字符,以重定向的stdin的方式工作,以便在輸入未重定向時可以將字符回顯到屏幕上,並且可以檢測到EOF狀況?理想情況下,我希望有一些行爲類似getchar()函數。

+0

請問如果運行MS-真正的同樣的事情發生DOS? –

+1

@MichaelPetch我還沒試過!讓我明天檢查一下。 – fuz

+0

@MichaelPetch在真正的MS-DOS上(我測試過MS-DOS 6.02),除了^ Z甚至沒有在輸入被重定向時終止程序時,大多情況也是如此。另一個區別是,當輸入被重定向時,它被複制到終端。 – fuz

回答

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 'ABCDEF' 
+0

這段代碼真的很聰明。 – fuz

+0

似乎要做的伎倆。感謝您的幫助。 – fuz

+0

@fuz十六進制打印代碼真的太聰明瞭,因爲它本身不錯。它只會比你的代碼更快,因爲它每次打印兩位數字。如果你想要更短的代碼,那麼最好不要使用查找表,因爲表大於它所替代的代碼。 –