Programowanie g這郾iczka w asemblerze pod Linuksem

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:

Jak wida� schemat dzia豉nia naszego programu jest do嗆 prosty:

  1. Otworzy� /dev/console do zapisu. W przypadku niepowodzenia u篡� STDOUT
  2. Ewentualnie wywo豉� sys_ioctl z EDX=0 w celu wy陰czenia aktualnie trwaj帷ego d德i瘯u
  3. Tyle razy ile trzeba, wywo豉� sys_ioctl z odpowiednimi warto軼iami w EDX i korzysta� z funkcji sys_nanosleep
  4. Wywo豉� sys_ioctl z EDX=0 w celu wy陰czenia d德i瘯u
  5. Je郵i otworzyli鄉y /dev/console, zamkn望 ten deskryptor

Przyk豉dowy program wygl康a tak (u篡wanie za陰cznik闚 z mojej biblioteki nie jest konieczne - w kodzie m闚i�, jak i co zamieni�):


(przeskocz program)
; 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!


Spis tre軼i off-line (klawisz dost瘼u 1)
Spis tre軼i on-line (klawisz dost瘼u 2)
U豉twienia dla niepe軟osprawnych (klawisz dost瘼u 0)