.model tiny
.dosseg
.stack 512
.data
.code
.386
_main proc near
org 100h
start: push ds
pop es
mov si,offset SomeTune
mov dx,61h ; turn speaker on
in al,dx ;
or al,03h ;
out dx,al ;
mov dx,43h ; get the timer ready
mov al,0B6h ;
out dx,al ;
LoopIt: lodsw ; load desired freq.
or ax,ax ; if freq. = 0 then done
jz short LDone ;
mov dx,42h ; port to out
out dx,al ; out low order
xchg ah,al ;
out dx,al ; out high order
lodsw ; get duration
mov cx,ax ; put it in cx (16 = 1 second)
call PauseIt ; pause it
jmp short LoopIt
LDone: mov dx,61h ; turn speaker off
in al,dx ;
and al,0FCh ;
out dx,al ;
int 20h ; exit to DOS
_main endp
; this routine waits for specified milliseconds
PauseIt proc near uses ax bx cx dx
xor dx,dx ; cx = 16 = 1 second
mov ax,62500
mul cx
mov cx,dx
xor dx,dx
mov bx,offset PFlag
mov ax,8300h
mov [bx],al ; clear flag
int 15h
WaitForIt: cmp PFlag,00h
je short WaitForIt
ret
PauseIt endp
PFlag db 00h ; flag for pauseit routine
SomeTune dw 1397,08
dw 1397,08
dw 1397,08
dw 1318,06
dw 1244,16
dw 1046,04
dw 1108,04
dw 1174,04
dw 1244,04
dw 1174,08
dw 1244,08
dw 1318,08
dw 1396,08
dw 1480,08
dw 1568,16
dw 00h,00h
end
This code is meant to play sound trough the pc speaker, it compiles without errors, but when I start this app, I get error from the system something like 'illegal instruction'. Can someone make this code work?
if you are running under XP, the system does not allow direct I/O with the hardware
i know this is confusing, because they "allow" it with int 10h
when you talk to the vga board, the I/O is actually emulated by the OS
the program may work under win 98, for example, because it does allow this kind of I/O
use the search feature in this forum as well as google'ing the
web for ways to accomplish what you want to do
I have tried to find solution on the net but there ain't any, is it possible to make this code work on XP?
This is how you would do it in 32-bit windows xp-
.686
.model Flat, Stdcall
option Casemap :None
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data
SomeTune dw 1397,08
dw 1397,08
dw 1397,08
dw 1318,06
dw 1244,16
dw 1046,04
dw 1108,04
dw 1174,04
dw 1244,04
dw 1174,08
dw 1244,08
dw 1318,08
dw 1396,08
dw 1480,08
dw 1568,16
dw 00h,00h
.code
program:
lea esi,SomeTune
.repeat
movzx eax,word ptr [esi]
.break .if eax==0
movzx ecx,word ptr [esi+2]
imul ecx,(1000/16) ; an approximation to your original timing
add esi,4
invoke Beep,eax,ecx
.until zero?
ret
end program
Not the catchiest tune I've ever heard.
Note that Beep wants its timing in milliseconds, not sixteenths of a second, so your timing can be much tighter.
how should I compile this code? If I make it 32-bit it will open/close, if I make it as 16-bit it returns error that is kernel is not a vaild lib.
Hi,
I had a little trouble assembling it (I'm not too
familiar with .model), and I thought .model tiny
was for a *.COM program. And you put in a
stack. But once I got it to assemble, it terminates
as soon as it trys to execute an OUT. So what
Dave says seems to be happening in a Win2k
full screen session. Timer ports are protected?
Steve N.
Edit:
Sorry, that does not seem to be the problem.
Stepping through the program in DEBUG shows
a bad case of pilot error over here.
SRN
Edit #2
I had to get rid of the "ORG 100h" and put in a
".STARTUP" to get things working. So I get sound,
but my Win2k system does not process INT 15
correctly. Maybe yours does, good luck.
SRN
Edit #3
I booted up to another OS and the program now
runs. So fix up the directives at the top, and use
EXE2BIN to make it a COM executable. Your code
seems to work then.
QuoteNot the catchiest tune I've ever heard.
I'll go along with that.
SRN
Sorry, I forgot to say, assemble as a console program. (32-bit, not dos 16-bit)
e.g., save the code in tst.asm, and make a batch file like-
if exist "tst.obj" del "tst.obj"
if exist "tst.exe" del "tst.exe"
\masm32\bin\ml /c /coff "tst.asm"
\masm32\bin\Link /SUBSYSTEM:CONSOLE "tst.obj"
Sorry, I just realized we're in the 16-bit forum. Please ignore everything I said unless you want to do it in normal 32-bit windows mode rather than dos, which you implied by saying you wanted it to run under windows xp, not dos.
So I guess the answer to your question-
QuoteI have tried to find solution on the net but there ain't any, is it possible to make this code work on XP?
is no, you can't make the original code work directly in XP.