	format ELF executable 3

struc timer second, nanosec {
.second dd second
.nanosec dd nanosec
	}

	entry _start

segment  executable


_start:

  mov eax, GETUID
  int 80h
  test eax,eax
  jz cont
  mov eax, 4		  	  	
  mov ebx, 1
  mov ecx, notroot
  mov edx, notroot_len
  int 80h
  jmp exit
	
cont:
  mov eax,IOPERM         ;-"ioperm" (system call = 101).
  mov ebx,Port1          ;-Command port timer(2) adress.
  mov ecx,1              ;-One adress to valid.
  mov edx,Port1
  int 80h 

  mov eax,IOPERM         ;-"ioperm" (system call = 101).       
  mov ebx,Port2          ;-Basis adress of "8254 timer".
  mov ecx,4              ;-Four successives adresses to valid.
  mov edx,Port2
  int 80h 

  in al,61h		; Read Port B
  or al,00000011b	; Timer 2 gate ON
  out 61h,al		; Write it back

  mov ecx, 6000
  mov edx, 600

loop1:
  mov ebx, ecx
  call frqsound
  call delay
  add ebx, 1000
  call frqsound
  call delay
  mov ebx,edx
  call frqsound
  call delay
  add ebx, 1000
  call frqsound
  call delay

  sub ecx,HIGH_PITCHDEC
  add edx,LOW_PUTCHINC
  cmp ecx,10
  jg loop1

exit:	
  call soundonoff

  mov eax,1              ;-"exit" (system call = 1).
  xor ebx,ebx            ;-Return code = 0.
  int 80h

delay:
  push eax
  push ebx
  push ecx
  push edx
  mov eax, NANOSLEEP
  mov ebx, timer1
  mov ecx, timer2
  int 80h
  pop edx
  pop ecx
  pop ebx
  pop eax
  ret
	
frqsound:
  push eax               ;-Save the context.
  push edx 
  mov ax,Fclkl           ;-Frequency divisor calculation.
  mov dx,Fclkh 
  div bx 
  out 42h,al             ;-Frequency divisor writting in "8254 timer"
  mov al,ah              ; timer(2) latches. 
  out 42h,al 
  pop edx                ;-Reload the context.
  pop eax 
  ret            

soundonoff:
  push ax 
  in al,61h		; Read Port B
  and al,11111100b	; Disable Timer 2 and speaker
  out 61h,al		; Write it back
  pop ax 
  ret	      



	
segment readable writeable
  timer1 timer 0, 8500000
  timer2 timer 0, 0
  notroot db 'Must be root.',0Ah,0
  notroot_len = $ - notroot
  NANOSLEEP = 162
  GETUID    = 24
  IOPERM    = 101
  Octcmd    = 0B6h                ;-Command word for "8254 timer" command
  ; register.
  HIGH_PITCHDEC = 200
  LOW_PUTCHINC = 5
  Fclkl     = 34DCh               ;-Clock frequency least significant byte.
  Fclkh     = 0012h               ;-Clock frequency most significant byte.
  Port1     = 61h                 ;-Gate adress port for (unabled / disabled)
  ; "8254 timer" timer(2).
  Port2     = 40h                 ;-Basis "8254 timer" adress.
	
