从文件中读取并在Assembly中输出其内容

时间:2013-04-02 13:24:07

标签: assembly file-io tasm dosbox

美好的一天!我听到了一个代码片段,它使用视频模式10h打印欢迎消息(菜单)。按下4时,它应从文件中读取并在屏幕上显示其内容。但是,它显示垃圾值,我必须打开DosBox并重新安装。

.model small 
.stack 1024 
.data 

MENU        DB 10,""
            DB 10,"          Welcome       "    ;24
            DB 10,""
            DB 10,"1 Novice"                ;3, 9
            DB 10,"2 Boss"                  ;3, 6
            DB 10,"3 Superb"                ;3, 11
            DB 10,"4 Scores"    
            DB 10,""
            DB 10,"Choice: ","$"                ;8

ROW1 DB 5   
ROW2 DB 10
COL DB 25       

Choice DB ?

; OTHER DECLARATIONS FOR COLORING I WON'T SHOW FOR SIMPLICITY

FileName DB "file.txt",0,8 ; name of file to open 
Handle   DW ?   ; to store file handle 

BufferSeg   dw  0

ErrMsgOpen  db  "Error opening `"
FileLength dw 0

nextLine    db  13,10

.code 

DisplayFile PROC NEAR

    ;escape to video mode
    mov ax,0A000h
    mov es,ax
    xor di,di
    xor ax,ax
    mov cx,32000d
    cld
    rep stosw

    mov     ax,cs
    mov     ds,ax
    mov     bx,ss
    add     bx,200h/10h     ;get past the end of the file
    mov     [BufferSeg],bx  ;store the buffer segment

    ;call   WriteFile 
    push    ds

    mov     ax,cs
    mov     ds,ax
    mov     ax,3d00h    ;open file (ah=3dh)
    mov     dx,offset FileName
    int     21h
    mov     bx,ax       ;move the file handle into bx

    mov     ds,[BufferSeg]
    mov     dx,0            ;load to [BufferSeg]:0000
    mov     ah,3fh
    mov     cx,0FFFFh       ;try to read an entire segments worth
    int     21h

    mov     [cs:FileLength],ax

    mov     ah,3eh
    int     21h             ;close the file

    cld
    mov     si,0
    mov     cx,[cs:FileLength]

    PrintLoop:
        mov     ah,2
        lodsb
        mov     dl,al
        int     21h         ;print a character

        dec     cx
        jne     PrintLoop

        pop     ds
        ret

    OpenError:
        mov     ah,9
        mov     dx,offset ErrMsgOpen
        int     21h

        pop     ds
        ret
DisplayFile ENDP 

.STARTUP
    mov     ax, @data 
    mov     ds, ax 

    @welcome:
        mov ax, 3
        int 10h

        MOV AX, 3       ; 80x25 color
        INT 10H         ; video BIOS call   
        MOV AH, 2       ; set cursor position
        MOV BH, 0       ; display page number
        MOV DH, ROW1        ; row number
        MOV DL, COL     ; column number
        INT 10H         ; video BIOS call
        LEA BP, ATT_BRICK       ; point to first attribute array 
        CALL FAR PTR STICK   ; display first line of video text


        ;scanf user's choice
        mov ah, 01h
        int 21h
        sub al, '0'
        mov Choice, al

        ; OTHER CODES

        cmp al, 4
        je @scores

    @score:
        call    DisplayFile

    @quit: 
        mov     ax, 4c00h       ;call dos to exit 
        int     21h 

.EXIT
END

基本上它是将结果保存在文件中的游戏。我可以正确地写入文件,但是当我尝试从中读取时,它不会在屏幕上输出。请帮我。非常感谢你!

修改
这与DisplayScore proc near所做的相同,但是在一个单独的asm文件中(只是为了测试从文件读取是否有效)。

 .MODEL SMALL
    .STACK 200h
    .CODE
    Ideal

;===- Data -===

BufferSeg   dw  0

ErrMsgOpen  db  "Error opening `"
FileName    db  "file.txt",0,8,"'$"     ;8 is a delete character

                                        ;0 is required for filename 
                                        ;(displays a space)
FileLength dw 0

buffer db "hehe$"
;===- Subroutines -===

PROC DisplayFile NEAR
    push    ds

    mov     ax,cs
    mov     ds,ax
    mov     ax,3d00h    ;open file (ah=3dh)
    mov     dx,offset FileName
    int     21h
    jc      OpenError
    mov     bx,ax       ;move the file handle into bx

    mov     ds,[BufferSeg]
    mov     dx,0            ;load to [BufferSeg]:0000
    mov     ah,3fh
    mov     cx,0FFFFh       ;try to read an entire segments worth
    int     21h

    mov     [cs:FileLength],ax

    mov     ah,3eh
    int     21h             ;close the file

    cld
    mov     si,0
    mov     cx,[cs:FileLength]
PrintLoop:
    mov     ah,2
    lodsb
    mov     dl,al
    int     21h         ;print a character

    dec     cx
    jne     PrintLoop

    pop     ds
    ret

OpenError:
    mov     ah,9
    mov     dx,offset ErrMsgOpen
    int     21h

    pop     ds
    ret
ENDP DisplayFile

;===- Main Program -===

START:
    mov     ax,cs
    mov     ds,ax
    mov     bx,ss
    add     bx,200h/10h     ;get past the end of the file
    mov     [BufferSeg],bx  ;store the buffer segment

    ;call   WriteFile
    call    DisplayFile

    mov     ax,4c00h
    int     21h
END START

1 个答案:

答案 0 :(得分:0)

如果我们启动我们的应用程序,那么我们将成为DOS中的所有免费ram,因此我们无法知道我们实际可以使用多少ram以及为DOS和TSR-Drivers保存哪些段地址。因此我们必须向DOS回馈我们此时尚未需要的所有ram,之后我们可以从DOS开始请求一个新指定的公羊,从一个持续拥有免费ram的段地址开始,这些ramnts不是DOS或驱动程序使用的

          call SETFREE               ; calculate the amoung of ram that we need
                                     ; for running our application and giviving
                                     ; back the rest of ram to DOS

          mov      bx, 2000h         ; request/reserv 128 KB ram from DOS
          call GETSPACE
          jc  NOSPACE                ; Error!
          mov      [NEWSEG], ax      ; save segment address


;------------------------------------
SETFREE:  mov      bx, ss            ; First we subtract both segmentaddresses
          mov      ax, es            ; for to become the amoung of paragraphs
          sub      bx, ax            ; from the PSP to the beginning of the stack.
          mov      ax, sp            ; Because our stackpointer beginn at the end
          add      ax, 0Fh           ; of the stacksegment, we can use the stackpointer
          shr      ax, 4             ; for the length of the stack.
          add      bx, ax
          mov      ah, 4Ah           ; Set new size
          int    21h
          ret
;------------------------------------
GETSPACE: mov      ah, 48h           ; BX = number/16
          int    21h
          ret