Do sometimes think about how would it be if your programs had not only visual effects, but also some sound?
Programming the sound cards (especially the modern ones) can be quite troublesome. Fortunately, the good old PC-speaker is a device which you can program quite easily. This is what I'm going to prove here. First some theory.
Linux is an operating system which works fully in protected mode. This is why we can't use the interesting (42h, 43h, 61h) input/output ports directly without root privileges.
Fortunately, the system function sys_ioctl (number 54) will help us in bringing the PC-speaker alive. This function expects the following parameters:
But this is not all. We'd like our sound to last for a while. For that we'll use the system function sys_nanosleep (number 162). Its syntax is simple:
struc timespec { .tv_sec rd 1 .tv_nsec rd 1 }containing number of seconds and nanoseconds to wait for.
As you can see, the algorithm of our program is simple:
Example program follows (using my library isn't necessary - the comments tell what to change):
; A program making sounds from the PC-speaker using sys_ioctl ; Author: Bogdan D. ; Contact: bogdandr (at) op (dot) pl ; ; assemble: ; fasm spkr.asm spkr format ELF executable entry _start segment readable executable include "bibl/incl/linuxbsd/fasm/fasm_system.inc" KIOCSOUND = 0x4B2F _start: mov eax, sys_open ; sys_open = 5 mov ebx, konsola mov ecx, O_WRONLY ; O_WRONLY = 1 mov edx, 777o int 80h cmp eax, 0 ; was there an error (EAX < 0) ? jg .otw_ok mov eax, 1 ;if we didn't open the console, use STDOUT (1) .otw_ok: mov ebx, eax ; EBX = file handle mov eax, sys_ioctl ; sys_ioctl = 54 mov ecx, KIOCSOUND xor edx, edx ; turning off the current sound int 80h mov eax, sys_ioctl mov edx, 2711 ; 2711 = 1234DDh/440. 440 Hz is the 'A' note int 80h mov cx, 0fh mov dx, 4240h ; 0F4240h is 1 decimal million in hexadecimal call pauza mov eax, sys_ioctl mov ecx, KIOCSOUND xor edx, edx ; turning off the sound int 80h cmp ebx, 2 ; check if using /dev/console or STDOUT jbe .koniec mov eax, sys_close ; sys_close = 6 int 80h ; close the open console file .koniec: mov eax, 1 xor ebx, ebx int 80h pauza: ;procedure pausing for CX:DX milliseconds push ebx push ecx push edx mov ax, cx shl eax, 16 mov ebx, 1000000 mov ax, dx ; EAX = CX:DX xor edx, edx div ebx ; divide CX:DX by 1 million mov [t1.tv_sec], eax ; EAX = number of seconds mov ebx, 1000 mov eax, edx ;EAX = number of microseconds left mul ebx mov [t1.tv_nsec], eax ; EAX = number of nanoseconds mov eax, sys_nanosleep ; function number 162 mov ebx, t1 mov ecx, t2 int 80h pop edx pop ecx pop ebx ret segment readable writeable konsola db "/dev/console", 0 struc timespec { .tv_sec rd 1 .tv_nsec rd 1 } t1 timespec t2 timespec
I hope to have given enough information for you to start programming the speaker on your own. If the program isn't working, you may need to compile pc-speaker support into your kernel (or insert the needed modules). Sometimes root privileges are necessary.
Have fun!