To make your programs more attractive to the eye and show off with your skills,
you can make the keyboard LEDs, showing the state of the
Num Lock, Caps Lock, Scroll Lock keys, flash in some way.
Now I'll show you how to do it.
To manipulate a character device (the keyboard) use the sys_ioctl system call (number 54). First you need to know what commands to use. To get those, read the /usr/include/linux/kd.h file or the manual, if you have the ioctl_list page. There we have:
#define KDGETLED 0x4B31 /* get current LED status */ #define KDSETLED 0x4B32 /* set new LED status */ #define LED_SCR 0x01 /* scroll lock */ #define LED_NUM 0x02 /* num lock */ #define LED_CAP 0x04 /* caps lock */
One of the first two values will be
put into ECX.
Meanwhile, EBX should contain a descriptor of /dev/console open
for writing or the value 1, meaning the standard output device - STDOUT.
EDX will contain the last parameter: a value in the range 0-7, if we want to set the LED state,
or an address of a DWORD variable, which will receive the current LED state (also in the
range 0-7).
Now we can see what our program should do: save the current LED state, change them as you like
(and make it last - do pauses), bring back the old state.
Here's how such a program could look like (using my library isn't necessary - the comments
tell what to change.
; Program manipulates the keyboard LEDs
;
; Author: Bogdan D.
; Contact: bogdandr (at) op (dot) pl
;
; nasm -f elf klaw.asm
; ld -s -o klaw klaw.o
section .text
; you don't have to use these:
%include "bibl/incl/linuxbsd/nasm/n_system.inc"
%include "bibl/incl/linuxbsd/nasm/n_const.inc"
%define KDGETLED 0x4b31
%define KDSETLED 0x4b32
global _start
_start:
; 1. open /dev/console, in write-only mode or use STDOUT
mov eax, sys_open ; sys_open = 5 (open the file)
mov ebx, konsola ; address of the file name
mov ecx, O_WRONLY ; O_WRONLY = 01
mov edx, 777q ; RWX for all
int 80h
cmp eax, 0
jge .ok ; continue if no error
; if error, use STDOUT
mov eax, stdout ; stdout = 1
; 2. get current LED state
.ok:
mov ebx, eax ; EBX = file descriptor
mov eax, sys_ioctl ; sys_ioctl = 54 - device manipulation
mov ecx, KDGETLED ; get led state
mov edx, stare_diody ; address of a DWORDa for the
; current LED state
int 80h
mov eax, sys_ioctl ; sys_ioctl = 54
mov ecx, KDSETLED ; set LED state
mov edx, 7 ; all set to "on"
int 80h
mov cx, 7
mov dx, 0a120h ; delay for half a second
call pauza
; bring back the old state
mov eax, sys_ioctl
mov ecx, KDSETLED ; set LED state
mov edx, [stare_diody] ; EDX = previous LED state
int 80h
cmp ebx, stdout ; did we open the console or STDOUT?
jle .koniec ; don't close the STDOUT
mov eax, sys_close ; close the open console file
int 80h
.koniec:
wyjscie ;
; mov eax, 1
; xor ebx, ebx
; int 80h
pauza: ; procedure pausing for CX:DX miliseconds
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 + timespec.tv_sec], eax ; EAX = number of seconds
mov ebx, 1000
mov eax, edx ; EAX = number of microseconds left
mul ebx
mov [t1 + timespec.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
section .data
stare_diody dd 0
konsola db "/dev/console",0
; The timespec structure is defined in n_system.inc (from my library)
;struc timespec
; .tv_sec: resd 1
; .tv_nsec: resd 1
;endstruc
t1 istruc timespec
t2 istruc timespec
Further experiments are left as an excercise for the user. Remember there are 8 different possible combinations for the LED state and you can make the different durations between state changes.
Have fun.