Czy nie my郵icie czasem, jakby to by這, gdyby mo積a by這 wzbogaci� sw鎩 program opr鏂z efektu wizualnego, tak瞠 o efekt d德i瘯owy?
Programowanie kart d德i瘯owych (zw豉szcza tych nowoczesnych) mo瞠 sprawia� niema貫 k這poty. Stary, poczciwy PC-Speaker jest jednak urz康zeniem wzgl璠nie prostym w programowaniu i to w豉郾ie tutaj udowodni�. Najpierw troszk� teorii, potem - do dzie豉!
Linux jest systemem dzia豉j帷ym w pe軟i w trybie chronionym. Dlatego bez uprawnie� administratora nie mo瞠my bezpo鈔ednio pisa� do interesuj帷ych nas port闚 (42h, 43h, 61h).
Na szcz窷cie istnieje funkcja systemowa sys_ioctl (numer 54) i to ona nam pomo瞠 w o篡wieniu g這郾iczka systemowego. Funkcja ta jako parametry przyjmuje:
Ale to nie wszystko. Chcemy, by nasz d德i瘯 chwil� potrwa�. W tym celu skorzystamy z funkcji sys_nanosleep (numer 162). Jej sk豉dnia jest prosta:
struc timespec
{
.tv_sec rd 1
.tv_nsec rd 1
}
i zawieraj帷ej wpisane ilo軼i sekund i nanosekund, kt鏎e nale篡 odczeka�.Jak wida� schemat dzia豉nia naszego programu jest do嗆 prosty:
Przyk豉dowy program wygl康a tak (u篡wanie za陰cznik闚 z mojej biblioteki nie jest konieczne - w kodzie m闚i�, jak i co zamieni�):
; Program wytwarzaj帷y d德i瘯i z g這郾iczka przez sys_ioctl
; Autor: Bogdan D.
; Kontakt: bogdandr (at) op (dot) pl
;
; kompilacja:
; 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 ; czy wyst徙i� b陰d (EAX < 0) ?
jg .otw_ok
mov eax, 1 ; jak nie otworzyli鄉y konsoli, piszemy
; na STDOUT (1)
.otw_ok:
mov ebx, eax ; EBX = uchwyt do pliku
mov eax, sys_ioctl ; sys_ioctl = 54
mov ecx, KIOCSOUND
xor edx, edx ; wy陰czenie ewentualnych d德i瘯闚
int 80h
mov eax, sys_ioctl
mov edx, 2711 ; 2711 = 1234DDh/440. 440 Hz to d德i瘯 A
int 80h
mov cx, 0fh
mov dx, 4240h ; 0F4240h to 1 milion dziesi皻nie
call pauza
mov eax, sys_ioctl
mov ecx, KIOCSOUND
xor edx, edx ; wy陰czamy d德i瘯
int 80h
cmp ebx, 2 ; sprawdzamy, czy u篡wamy /dev/console
; czy STDOUT
jbe .koniec
mov eax, sys_close ; sys_close = 6
int 80h ; zamykamy otwarty plik konsoli
.koniec:
mov eax, 1
xor ebx, ebx
int 80h
pauza: ;procedura pauzuj帷a przez CX:DX milisekund
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 ; CX:DX dzielimy przez milion
mov [t1.tv_sec], eax ; EAX = liczba sekund
mov ebx, 1000
mov eax, edx ;EAX = pozosta豉 liczba mikrosekund
mul ebx
mov [t1.tv_nsec], eax ; EAX = liczba nanosekund
mov eax, sys_nanosleep ; funkcja numer 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
Mam nadziej�, 瞠 poda貫m wystarczaj帷o informacji, aby軼ie samodzielnie zacz瘭i programowa� g這郾iczek. Je郵i mi si� nie uda這, to zawsze mo瞠cie skorzysta� z gotowej procedury z mojej biblioteki.
Je郵i program nie powoduje wydawania 瘸dnych d德i瘯闚, mo瞠 trzeba wkompilowa� obs逝g� g這郾iczka do j康ra (lub za豉dowa� odpowiedni modu�). Czasem mog� by� potrzebne uprawnienia administratora.
To ju� koniec. Mi貫j zabawy!