2013-04-02 21 views
0

美好的一天!我聽到一個代碼片斷,它使用視頻模式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 
+0

你肯定'BufferSeg'有效嗎?你有嘗試過使用'int 21h' /'ah = 48h'來分配內存嗎? – Michael

+0

我試着在一個單獨的文件中將'DisplayScore proc near'分開,它可以工作,也就是說,它從文件中讀取並在屏幕上顯示內容。但是當我將它合併到視頻模式時,會發生垃圾值。請參閱編輯以查看單獨的asm文件,雖然它與DisplayScore相同。 –

+0

原始代碼是否可以編譯?你有一個'je @ scores',我認爲這是跳到下一行。但是這個標籤有'@ score'(不是''')。 – Michael

回答

0

如果我們開始我們的應用程序,然後我們成爲了所有從DOS免費的RAM,所以我們無法知道有多少RAM我們actualy可以使用和段地址被保存爲DOS和TSR-驅動程序。所以我們必須把DOS下所有那些我們還不需要的內存還給DOS,然後我們才能從DOS中請求一個新的任命內存,從一個連續有空閒內存的段地址開始,這個空閒內存是沒有用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 
相關問題