2013-04-02 11 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 
相关问题