Search code examples
assemblyx86tasmdosbox

Generating music tone using PC speaker


I have this code:

IDEAL
MODEL small
STACK 100h
DATASEG
CODESEG

PROC PLAY
        mov al, 182         
        out 43h, al          

        out 42h, al        
        mov al, ah          
        out 42h, al 
        in al, 61h         
        or al, 00000011b   
        out 61h, al        
        mov bx, 15         
pauseSound:
        mov cx, 65535
pause2:
        dec cx
        jne pause2
        dec bx
        jne pauseSound

        in  al, 61h         

        and al, 11111100b   
        out 61h, al         

        RET
    END PLAY

start:      


       mov ax, 2712
       call PLAY


       MOV AX, 3834
       call PLAY
exit :

    mov ax, 4C00h
    int 21h
    END start

That program needs to play one sound a couple of seconds, and then another sound for a couple of seconds. However I am only hearing the first one and not the second, where is the problem/bug?
Thank you


Solution

  • Directive END tells TASM to break the assembly and it specifies the program entry point, too. There should be only one such directive in TASM source, usually in the last line. Due to your typo error TASM only assembles the subroutine PLAY and it is not smart enough to warn you that PROC PLAY is not correctly terminated.

    Change END PLAY to ENDP PLAY and your program will work.

    Update: I assembled your program with

    > tasm Meow.asm
    Turbo Assembler  Version 4.0  Copyright (c) 1988, 1993 Borland International
    Assembling file:   Meow.asm
    Error messages:    None
    Warning messages:  None
    Passes:            1
    

    and then linked and run in DOSBox on Windows 10 64bit:

    > ver
    > DOSBox version 0.74-2. Reported DOS version 5.00.
    > tlink Meow.obj
    Turbo Link  Version 3.01 Copyright (c) 1987,1990 Borland International
    > Meow.exe
    >
    

    and it played two tones with high and low pitch, cca 0.8 seconds long each, and then exited, exactly as expected.

    If it plays only shortly on your system, try to increase timing constant mov bx, 15. You could also add some dummy instructions at pause2, but generally, measuring time by jne pause2 is very unreliable on newer computers, especially with emulators.