Hi! I am wondering what's wrong with my code. It's a simple code which is supposed to activate the PC speaker with a DO note.
I'm using XPmode on windows7 ultimate 32B SP1, with EMU86 as assembler, runnig the program with CMD (tried also dosbox).
The wierd thing is when I'm using a very similar, yet more complicated code (below) on the same machine it workes just fine.

My code:

.model small

.stack 100h

.data

.code

mov ax, @data
mov ds, ax 


mov al, 10110110b    ; move control word to timer
out 43h, al          ; set channel 2 enable           

mov ax, 2280         ; ax makes the frwquncy of a DO note 
out 42h, al          ; move first byte to timer counter

mov al, ah
out 42h, al          ; move second byte to timer counter 

mov al, ah           
in  al, 61h           ; get port B
or  al, 00000011b     ; set the two lsb to 1 - activate speaker
out 61h, al

mov  cx, 0FFFFh       ; wait for a few seconds
again1:
push cx
mov  cx, 0FFFFh
again2:
loop again2
pop  cx
loop again1

in  al, 61h           ; get port B
and al, 11111100b     ; set the two lsb to 0 - disable speaker
out 61h, al


mov ah, 4ch
int 21h

The other (working) code:

Control_Word_Channel_2  = 10110110b
Do_for_counter          = 2280
lsb_on                  = 00000011b
lsb_off                 = 11111100b 
Delay_count             = 0fffh      ;the delay for wait func 
timer_counter_channel2           = 042h     
control_word_address             = 043h
port_B                           = 61h 
keybord_pos                      = 64
insert_key                       = 60h




.model small
.stack 100h
.data
operand db 2
array dw  0, 2280, 2031, 1809, 1715, 1521, 1355, 1207, 1140
rec_array  dw 150 dup ('?') 
counter dw 0
rec_index dw 0
.code

mov ax, @data
mov ds, ax 


mov al, Control_Word_Channel_2
out 43h, al                       ;move control word to timer

call check_key                    ;check keyboard

mov ah, 4ch
int 21h



;***************************************************************
;func_name: play_on
;Play the wanted note 
;***************************************************************  
play_on:
    push ax                           ;save reg
    mov ah, 0                         ;init
    dec al                            ;dec the key_scan_code
    mul operand                       ;mul the key in order to get the right place in array
    mov bx, 0                         ;init
    mov bl, al                        ;bl- the index of the right note in array
    mov ax, [array][bx]               ;ax is the wanted note 
    out timer_counter_channel2, al    ;move first byte to timer counter
    call save                         ;save the note 
    add counter, 2                    ;count the note that was played
    mov al, ah
    out timer_counter_channel2, al    ;move seconed byte to timer counte 

    mov al, ah           
    in al, port_B                     ;get port B
    or al, lsb_on                     ;on the lsb 0 & 1
    out port_B, al                    ;make_sound
    pop ax
ret
;***************************************************************
;func_name: save
;save the note in the rec_array
;*************************************************************** 
save:
push bx
mov bx, counter             
mov [rec_array][bx], ax     ;insert the note in the rec_array
pop bx
ret
;***************************************************************
;func_name: play_off
;Play music :) 
;***************************************************************  
play_off:
    push ax
    in al, port_B                   ;get port B
    and al, lsb_off                 ;off the lsb 0 & 1
    out port_B, al                  ;stop- sound
    pop ax
ret
;***************************************************************
;func_name: play_rec
;Play the recorded music 
;*************************************************************** 
play_rec:
    pusha
    mov cx, counter                    
 again:
    mov bx, rec_index
    mov ax, [rec_array][bx]         ;ax is the wanted note
    out timer_counter_channel2, al  ;move first byte to timer counter
    mov al, ah
    out timer_counter_channel2, al  ;move seconed byte to timer counte
    in al, port_B                   ;get port B
    or al, lsb_on                   ;on the lsb 0 & 1
    out port_B, al                  ;make_sound
    call wait1                      ;delay
    call wait1
    call play_off                   ;off sound
    add rec_index, 2                ;the next place in rec-array
    cmp rec_index, cx
    jne again                       ;while rec_index!=counter
    mov rec_index, 0                ;init
    mov counter, 0                  ;init
    popa
ret
;**********************************************************************
;check_key
;key 1-8: play note
;key R  : replay
;key 9  ; exit 
;**********************************************************************         
check_key:
    cont:
    in al, keybord_pos        
    and al, 01
    cmp al, 1                   ;check if the lsb of 64h port is 1
    jnz cont
    in al, insert_key           ;insert the key code to al
    cmp al, 10                  ;if the key is 1-8- play
    jb play 
    je exit                     ;if the key is 9- exit
    cmp al, 13h                 ;if the key is R- replay
    je replay
    jmp cont
    play:
    call play_on                ;play sound
    call wait1                  ;delay
    call wait1
    call play_off               ;paly_off
    jmp cont          
    replay: 
    call play_rec               ;replay
    jmp cont                    ;check key again
    exit:
 ret
;***************************************************************
;func_name: wait1
;Cause delay 
;***************************************************************            

wait1:
pusha 
    mov cx, Delay_count
       wait_again2: mov dx, 0ffffh
                    wait_again1: 
                    dec dx
                    jnz wait_again1
                    loop wait_again2
popa
ret   

end      

I would be thankfull for any clue.

Thanks!

  This code worked for me...



mov     al, 182         ; Prepare the speaker for the
        out     43h, al         ;  note.
        mov     ax, 4560        ; Frequency number (in decimal)
                                ;  for middle C.
        out     42h, al         ; Output low byte.
        mov     al, ah          ; Output high byte.
        out     42h, al 
        in      al, 61h         ; Turn on note (get value from
                                ;  port 61h).
        or      al, 00000011b   ; Set bits 1 and 0.
        out     61h, al         

Edited 4 Years Ago by NotNull

I am surprised you can get it to work at all, Normally a mulitasking operating system won't let an application touch the hardware. After all, if every program tried to directly program the hardware, chaos would reign. What if Windows was using the 8253/4 to feed its scheduler, and somebody else was mucking around with it?

This article has been dead for over six months. Start a new discussion instead.