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 (Alt+1)
Spis tre軼i on-line (Alt+2)
U豉twienia dla niepe軟osprawnych (Alt+0)