int0h:
	mov	word[0b8002h],"0 "
	cli
	hlt
int1h:
	mov	word[0b8002h],"1 "
	cli
	hlt
int2h:
	mov	word[0b8002h],"2 "
	cli
	hlt
int3h:
	mov	word[0b8002h],"3 "
	cli
	hlt
int4h:
	mov	word[0b8002h],"4 "
	cli
	hlt
int5h:
	mov	word[0b8002h],"5 "
	cli
	hlt
int6h:
	mov	word[0b8002h],"6 "
	cli
	hlt
int7h:
	mov	word[0b8002h],"7 "
	cli
	hlt
int8h:
	mov	word[0b8002h],"8 "
	cli
	hlt
int9h:
	mov	word[0b8002h],"9 "
	cli
	hlt

int30h: 					;my first api :)
	push	ds
	push	10h
	pop	ds
	cmp	ah, 1
	jz	.checkkey
	cmp	ah, 2
	jz	.getkey
	pop	ds
	iret
     .checkkey:
	cmp	[keycount], 0
	pop	ds
	jz	.nokey
	and	byte [esp+8],not (1 shl 6)	; clear ZF
	iret
     .nokey:
	or	byte [esp+8],1 shl 6		; set ZF
	iret
     .getkey:
	push	ebx
	push	edi
	cli					;just in case
	inc	[keycount]
	xor	edx, edx			;[in] edi = buffer
     .getkeyloop:
	xor	eax, eax
	test	[keystatus], KSHIFT
	jz	.noshift
	mov	ecx, ASCIITableU
	jmp	@F
     .noshift:
	mov	ecx, ASCIITableL
     @@:
	movzx	eax, byte[keybuffer+edx]
	test	al, al
	sets	bl
	and	eax, 7fh
;        jns     @F
;     .keyup:
;        neg     al
;        mov     ebx, 1                           ;keyup
;     @@:
	mov	eax, [eax+ecx]
	cmp	al, 20h
	jc	.specialkeys
	cmp	bl, 1
	jz	.cont
	stosb
      .cont:
	xor	ebx, ebx
	inc	edx
	cmp	edx, [keycount]
	jnz	.getkeyloop
	and	[keycount], 0
	pop	edi
	pop	ebx
	pop	ds
	iret
     .specialkeys:
	cmp	al, 14h
	jz	.shift
	cmp	al, 15h
	jz	.shift
	cmp	bl, 1	 ;keyup
	jnz	.cont
	cmp	al, 18h
	jz	.cap
	cmp	al, 19h
	jz	.numlock
	cmp	al, 1ah
	jz	.scroll
	jmp	.cont
     .shift:
	cmp	bl,1
	jz	.shiftup
	or	[keystatus], KSHIFT
	jmp	.cont
     .shiftup:
	and	[keystatus], NOT (KSHIFT)
	jmp	.cont
     .cap:
	xor	[keystatus], KCAP
	call	setkeyboardled
	jmp	.cont
     .numlock:
	xor	[keystatus], KNUM
	call	setkeyboardled
	jmp	.cont
     .scroll:
	xor	[keystatus], KSCROLL
	call	setkeyboardled
	jmp	.cont

setkeyboardled:
	mov	al, 0edh
	out	60h, al
      .wait:
	in	al, 64h
	test	al, 8
	jnz	.wait
	mov	al, byte[keystatus]
	and	al, 111b
	out	60h, al
	ret

KSCROLL 	= 1h
KNUM		= 2h
KCAP		= 4h
KSHIFT		= 8h
KCTRL		= 10h
KALT		= 20h
KF1		= 1h
KF2		= 2h
KF3		= 3h
KF4		= 4h
KF5		= 5h
KF6		= 6h
KF7		= 7h
KF8		= 8h
KF9		= 9h
KF10		= 0ah
KEsc		= 10h
KBksp		= 11h
KEnter		= 12h
KCtrl		= 13h
KLShift 	= 14h
KRShift 	= 15h
KPrtScr 	= 16h
KAlt		= 17h
KCaps		= 18h
KNum		= 19h
KScrl		= 1ah

ASCIITableL:
DB 00, KEsc, "1234567890-=", KBksp, 20h
DB "qwertyuiop[]", KEnter, KCtrl, "asdfghjkl;'`", KLShift, "\zxcvbnm,./"
DB KRShift, KPrtScr, KAlt, " ", KCaps, KF1, KF2, KF3, KF4, KF5, KF6, KF7, KF8, KF9, KF10, KF1, KNum, KScrl

ASCIITableU:
DB 00, KEsc, "!@#$%^&*()_+", KBksp, 20h
DB "QWERTYUIOP{}", KEnter, KCtrl, 'ASDFGHJKL:"~', KLShift, "|ZXCVBNM<>?"
DB KRShift, KPrtScr, KAlt, " ", KCaps, KF1, KF2, KF3, KF4, KF5, KF6, KF7, KF8, KF9, KF10, KF1, KNum, KScrl

align 4
irq00:
	mov	word[0b8004h],"T "
	mov	al,20h
	out	20h,al
	iret
align 4
irq01:
	pushad
	push	ds
	push	10h
	pop	ds
	in	al, 64h
	test	al, 1
	jz	.nokey
	in	al, 60h
	mov	ecx, [keycount]
	cmp	ah, 0e0h
	jz	.nokey			;useless escape key
	cmp	ah, 0e1h
	jz	.nokey
	cmp	al, 0F0h
	ja	.nokey
     .copykey:
	mov	[keybuffer+ecx], al
	inc	ecx
	cmp	ecx, 32 		 ;buffer too small
	jz	.die
	mov	[keycount],ecx
     .nokey:
	mov	word[0b8000h],"K1"
	mov	al,20h
	out	20h,al
	pop	ds
	popad
	iret
     .die:
	dec	ecx
	jmp	.nokey

keybuffer rb 32
keycount dd 0
keystatus dd 0

dwtoh:
	push	edi
	mov	ecx, 8
	mov	ebx, [esp+4+4]
;        mov     esi, [esp+8+8]
	mov	edi, 0b8000h
@@loop_digit:
	rol	ebx,4
	mov	al,bl
	and	al,0Fh
	add	al, 90h 	; convert al to ascii hex
	daa			; only four instructions
	adc	al, 40h
	daa
	mov	ah, "1"
	stosw

	dec	ecx
	jnz	@@loop_digit
	xor	eax,eax
	mov	byte [esi],al
	pop	edi
	retn 4

idt:
	dw idtsize-1
	dd .idtbase
align 4
.idtbase:
;int 0
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 1
	dw int1h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 2
	dw int2h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 3
	dw int3h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 4
	dw int4h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 5
	dw int5h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 6
	dw int6h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 7
	dw int7h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 8
	dw int8h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 9
	dw int9h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 10
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 11
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 12
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 13
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 14
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 15
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 16
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 17
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 18
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 19
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 20
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 21
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 22
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 23
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 24
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 25
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 26
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 27
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 28
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 29
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 30
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 31
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 20h
	dw irq00		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 21h
	dw irq01		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 22h
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 23h
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 24h
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 25h
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 26h
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 27h
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 28h
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 29h
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 2Ah
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 2Bh
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 2Ch
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 2Dh
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 2Eh
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 2Fh
	dw int0h		;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
;int 30h
	dw int30h		 ;address of handler
	dw 8			;code segment
	db 0
	db 10001110b		; P=1,dpl=00,0,d=1=32bit,xxx
	dw 0
idtsize = $-.idtbase