I am making a small game in MS-DOS using Assembly language and compiling with Borland Turbo Assembler 5.0, currently I am in phase of testing different parts of the game separately (like text and graphics screens as well as PC Speaker sound). While testing out onboard PC Speaker sound (I'm using VMware Worstation Player for emulation), the program compiles just fine, but first of all, it never ends (gets stuck, I have to reboot the virtual machine to get out of stuck loop), second of all, the sound is still on (gets cleared when rebooted, thankfully), and third of all, the frequency is totally different than I expected.
This is my code:
; Testovací sekvence hry Lodě (LODE.COM)
; Testing sequence of game Lodě (Boats; LODE.COM)
P8086           ; Výběr procesoru  // CPU
MODEL TINY      ; => ZASAH.COM
DATASEG
Beep    DW 0BA7h        ; Frekvenční číslo 2983 = 400 Hz      // Frequency number
Len     DW 0001h        ; HIWORD => Délka 100 ms = 100 000 us // Length of the beep
        DW 86A0h        ; LOWORD
UDATASEG
Stck    LABEL WORD
CODESEG
        STARTUPCODE
        MOV     SP,OFFSET Stck  ; Odložme si stack  // Save our stack
        CALL    Begin
        MOV     AH,4Ch
        INT     21h
        RET
Begin PROC NEAR
        mov     bx,[OFFSET Beep]        ; Nastavme si frekvenci 400 Hz  // Set frequency
        CALL    BeepStrt
        mov     cx,[OFFSET Len]         ; Nastavme si 100 ms prodlevu   // Set delay
        mov     dx,[OFFSET Len+1]
        CALL    Delay
        CALL    BeepEnd
        ret
Begin ENDP
BeepStrt PROC NEAR
        in      al,61h          ; Stáhnout hodnotu portu 61h  // See value of port 61h
        or      al,03h          ; Zapnout bity 0 a 1          // Set bits 0 and 1
        out     61h,al          ; Poslat zpět do portu 61h    // Update port 61h
        ret
BeepStrt ENDP
BeepEnd PROC NEAR
        in      al,61h          ; Stáhnout hodnotu portu 61h  // See value of port 61h
        and     al,0FCh         ; Vypnout bity 0 a 1          // Reset bits 0 and 1
        out     61h,al          ; Poslat zpět do portu 61h    // Update port 61h
        ret
BeepEnd ENDP
Delay PROC NEAR
        mov     ah,86h          ; BIOS funkce prodlevy                // BIOS delay func
                                ; Právě teď máme nastavenou prodlevu  // We now have delay set
        int     15h             ; Provedeme                           // Let's do it
        ret
Delay ENDP
END
No matter if I use the offset Len +1 or +2, it didn't even work when I fed it the values directly. When I was testing it few years ago with standard MS-DOS program DEBUG.EXE, it worked perfectly. It doesn't with TASM. I want to use TASM, because it's really pain in the *** to write it all with DEBUG. Source code file and compiling using TASM (and of course linking with TLINK) is much easier and much more convenient. Allas, the end result should always be the same, right?
This is the screenshot of it get stuck:

And I've got my informations from these sources:
One thing actually popped in my head. What will happen if the actual program exceeds 64k size? Will TASM/TLINK prevent it from compiling and/or linking and tells that the resulting program is too big, or it will compile up to 64k and rest will be truncated? I've put myself to a challenge to build entire program to fit in 64k size. Otherwise, I can always rename .EXE to .COM, it will work anyway. However, it makes sense for a program used as a command, rather than a simple game.