Hallo,
ich versuche ein Programm (NASM als Assembler) zu schreiben, welches eigentlich ganz simpel ist:
-> Einen 64 KB-Puffer bereitstellen
-> darin 64 KB einer Datei lesen
-> diese Datei an LPT1 senden (direkt über die Ports).
Hintergrund: An LPT1 (Basisport 0x378) hängt ein DAC, mit dem ich Audiodaten an einen Verstärker senden kann. Timing spielt (noch) keine Rolle, das kann ich mit einer Schleife vorerst verzögern.
Mein Problem: In dem Moment, wo ich den int 21h aufrufe, bricht mein gesamtes Programm zusammen. Den Code zum Berechnen der aktuellen Programmgröße habe ich aus dem Netz.
Vielleicht kann mir jemand helfen; ich poste einfach mal den gesamten Code.
;------------------------------------
;- PLAYER -
;- Play RAW audio files on DAC/LPT1 -
;------------------------------------
org 100h
; set program's memory size to 64K (limit of "tiny" COM files) - CS=DS=ES=SS
mov bx,ss
mov ax,es
sub bx,ax
mov ax,sp
add ax,14h
shr ax,4
add bx,ax
mov ah,04ah
int 21h
; get memory (64K)
mov ah,48h
mov bx,1000h ; 4096 * 16 Bytes = 64 KBytes
int 21h
push ax
; open the file
mov ah,3Dh
mov al,0 ; read only
mov dx,FILENAME ; ds:dx = ASCIIZ filename
int 21h
jc err_fopen
mov [FILEHANDLE],ax
pop ds ; new DS => DS:BX addresses file buffer
; main program loop
;===================
beginmain:
; read (next) 64K of file
mov ah,3Fh
mov bx,[cs:FILEHANDLE]
mov cx, 0ffffh
mov dx,0
int 21h
jc err_fread
mov ah,09h
mov dx,msg_debug
int 21h
mov bx,0 ; begin at address 0 of buffer
mov dx,[BASE_ADDR] ; dx = BASE_ADDR
play:
mov al,[ds:bx]
out dx,al
inc bx
loop play
endmain:
;===================
; end main loop
; close the file
mov ah,3Eh
mov bx,[FILEHANDLE]
int 21h
jc err_fclose
; deallocate the memory
mov ah,49h
int 21h
jc err_memclose
jmp end
; write error messages
err_fopen:
mov ah,09h
mov dx,msg_err_fopen
int 21h
jmp end
err_fclose:
mov ah,09h
mov dx,msg_err_fclose
int 21h
jmp end
err_fread:
push cs
pop ds
mov ah,09h
mov dx,msg_err_fread
int 21h
jmp endmain ; end the program
err_memresize:
mov ah,09h
mov dx,msg_err_memresize
int 21h
jmp end
err_memclose:
mov ah,09h
mov dx,msg_err_memclose
int 21h
jmp end
err_memget:
mov ah,09h
mov dx,msg_err_memget
int 21h
jmp end
; exit program
end:
mov ah,4Ch
mov al,00h
int 21h
msg_debug db "DEBUG",13,10,36
msg_err_fopen db "Could not open the file!",13,10,36
msg_err_fclose db "Could not close the file!",13,10,36
msg_err_fread db "Could not read the file!",13,10,36
msg_err_memresize db "Could not resize program's memory!",13,10,36
msg_err_memget db "Could not allocate enough memory (64K)!",13,10,36
msg_err_memclose db "Could not deallocate the memory!",13,10,36
FILENAME db "QUAAK.AU",0
FILEHANDLE dw 0
BASE_ADDR dw 0378h
HAVE_NEXTBLOCK db 0
Warum ich nicht in einem Segment bleiben möchte? Wenn ich mit 48h Speicher beschaffe, ist der unabhängig vom Programm und ich kann darauf dann eine Interrupt-Routine draufschmeißen. Außerdem kann ich so den Puffer maximieren.
Achja: Bitte keine 32-Bit-Addressierungen verwenden, das Gerät ist ein 286er.
Gruß,
ein völlig korrupter
Sebastian