ORG 100h
SEGMENT	_TEXT ;start=0 vstart=100h

RMMSGID_V86ALREADY EQU 0
RMMSGID_DOSRESIZE  EQU 1
RMMSGCOUNT	   EQU 2

main:
CPU 386
BITS 16
	smsw	ax
	test	ax, 1
	jnz .v86already
	;
	mov	sp, stack_ends
	mov	bp, bss_starts
	;
	mov	bx, sp
	add	bx, 15
	shr	bx, 4
	mov	ah, 4Ah
	int 21h
	jc .dosresize
	;
BSS_GDTR  EQU  2    ; align properly at odd word address
	mov	word [bp+BSS_GDTR], our_gdt.end-our_gdt-1  ; GDT upper limit
	mov	ax, cs
	xor	dx, dx
	mov	dl, ah
	mov	cl, 4
	shr	dx, cl
	shl	ax, cl
	add	[our_gdt.sel08+2], ax  ; base addr bits 0-15
	adc	[our_gdt.sel08+4], dl  ; base addr bits 16-24
	add	[our_gdt.sel10+2], ax  ; base addr bits 0-15
	adc	[our_gdt.sel10+4], dl  ; base addr bits 16-24
	mov	cx, ax  ; save
	mov	bx, dx  ;  "
	add	ax, our_gdt
	adc	dl, 0
	mov	[bp+BSS_GDTR+2], ax  ; GDT lin. addr; low word
	mov	[bp+BSS_GDTR+4], dx  ; " high word
BSS_OLD_SEG EQU 8
BSS_IDTR    EQU 0Ah  ; should be at odd word addr.
BSS_SAVE_IDTR EQU 0x12 ; likewise
BSS_SAVE_GDTR EQU 0x1A ; likewise
int3
	sgdt	[bp+BSS_SAVE_GDTR]
	sidt	[bp+BSS_SAVE_IDTR]
	mov	word [bp+BSS_IDTR], our_idt.end - our_idt - 1 ; IDT limit
	mov	ax, cx  ; restore ax
	mov	dx, bx  ;  and dx
	add	ax, our_idt
	adc	dl, 0
	mov	[bp+BSS_IDTR+2], ax
	mov	[bp+BSS_IDTR+4], dx
	mov	[bp+BSS_OLD_SEG], cs
	;
int3
mov ax,0xB800
mov es, ax
mov di, (24*80+79)*2
mov ax, 0x0F00 + 'A'
stosw
int3
	; fixup selector part of IDT entries
	mov	cx, (our_idt.end - our_idt) / 8 + 1
	mov	di, our_idt+2
.iloop:	mov	word [di], 08h  ; 08 is code segment selector.
	add	di, 8   ; advance 1 IDT entry.
	loop .iloop
call waitesc16
;in al,70h  ; disable NMI
;or al,80h
;out 70h,al
	cli
	lgdt	[bp+BSS_GDTR]
	lidt	[bp+BSS_IDTR]
	mov	eax,cr0
	or	al, 1
	mov	cr0,eax
mov ax, 10h  ; data/stack selector
mov ds, ax
movzx esp,sp
mov ss, ax
add al, 8	; 18h = video selector
mov es, ax
mov di, (24*80+79)*2
mov ax, 0x0F00 + 'B'
stosw
;jmp $
call waitesc16
push word 08h
push dword .pm32ent
retfd
ALIGN 4
BITS 32
.pm32ent:
movzx esp,sp
movzx ebp,bp
mov edi, (24*80+79)*2
mov ax, 0x0F00 + 'C'
stosw
;jmp $
sti
call waitesc32
	cli
	mov	eax,cr0
	and	eax, ~(1|0x80000000)  ; clear PE and PG bits
	mov	cr0,eax
	lidt	[ebp+BSS_SAVE_IDTR]
	lgdt	[ebp+BSS_SAVE_GDTR]
mov ax, 0xB800
mov es, ax
mov ax, [ebp+BSS_OLD_SEG]
mov ds, ax
mov ss, ax
call waitesc32
;.kbloop2:
;in al, 60h
;cmp al, 1
;jne .kbloop2
mov edi, (24*80+79)*2
mov ax, 0x0F00 + 'D'
stosw
;jmp $
mov ax,[ebp+BSS_OLD_SEG]
;mov cs,ax
push word ax
;push word 0
;push dword .exit32
;retfd
BSS_EXIT32_ADDR EQU 0x20
mov word [ebp+BSS_EXIT32_ADDR], .exit32
mov word [ebp+BSS_EXIT32_ADDR+4], 0 ; xxx
mov word [ebp+BSS_EXIT32_ADDR+2], ax
jmp far [ebp+BSS_EXIT32_ADDR]
push word .exit32
retfw
ALIGN 4
BITS 16
.exit32:
mov edi, (24*80+79)*2
mov ax, 0x0F00 + 'E'
stosw
jmp $
.kbloop0:
in al, 60h
cmp al, 1
jne .kbloop0
;sti
mov edi, (24*80+79)*2
mov ax, 0x0F00 + 'F'
stosw
.kbloop1:
in al, 60h
cmp al, 1
jne .kbloop1
;BITS 16
mov ax,4C00h
int 21h

mov eax,cr0
and eax, ~1
mov cr0,eax
int 20h
int3

	mov	ax, 08h  ; 08 is the code segment selector
	mov	cs, ax
	mov	ax, 10h  ; data/stack descriptor
	mov	ds, ax
	mov	ss, ax
	mov	ax, 18h  ; 18h is a descriptor for VGA text memory
	mov	es, ax
	push	cs
	push	word 0
	push	word .pmentry
	retfd
.pmentry:
BITS 32
	mov	word es:[0], 0x0F00 + 'x'
	sti
	;
	cli
	mov	eax,cr0
	and	al, ~1
	mov	cr0,eax
	sti
	push	word [bp+BSS_OLD_SEG]
	push	dword .pmexit
	retfd
.pmexit:
	mov	ax, [bp+BSS_OLD_SEG]
	mov	cs, ax
	mov	ds, ax
	mov	ss, ax
	;
	mov	ax, 4C00h
	int 21h
.v86already:
	mov	ax, RMMSGID_V86ALREADY
.err_common:
	mov	bx, rmmsgtab
	mov	cx, 2		;stderr fd
	call outmsgid
	mov	ax, 4C01h	; terminate w/ error
	int 21h
.dosresize:
	mov	ax, RMMSGID_DOSRESIZE
	jmp short .err_common

BITS 16
; entry:
;   AX    = message ID.
;   BX    = msgtab. ptr.
;   CX    = file handle
;   DS    = message segment
; return:
;   CY if error
outmsgid:
	push	ax
	push	bx
	push	dx

	push	cx
	call msglookup		; get DX=msg.ptr, CX=msg.len.
	pop	bx		; BX<=file handle that was in CX
	jc .ret			; lookup failed

	mov	ah, 40h		; DOS write syscall#
	int 21h
	jc .ret

	mov	dx, msg_crlf
	mov	cx, 2
	mov	ah, 40h
	int 21h

.ret:	mov	cx, bx
	pop	dx
	pop	bx
	pop	ax
	ret


; entry:
;   AX = msg id.
;   BX = table ptr.
; return:
;   CX = length of msg.
;   DX = offset of msg.
; error return:
;   CF set
msglookup:
	push	ax
	push	bx
	cmp	ax, [bx-2]	; message count
	jae .crlf
	add	ax, ax		; AX = msg.id * 2
	add	bx, ax
	mov	dx, [bx]	; load message offset
	mov	cx, [bx+2]	; next msg. offset
	sub	cx, dx		; calc. length
.ret:	pop	bx
	pop	ax
	ret
.crlf:	cmp	ax, -1		; -1 is a special msg. id for CR-LF
	jc .ret			; c: AX wasn't -1 ; returning CY=error
	mov	cx, 2		; length
	mov	dx, msg_crlf
	jmp short .ret

BITS 16
waitesc16:
	pushf
	push	ax
.1:	in	al, 60h
	cmp	al, 1
	jne .1
.2:	in	al, 60h
	cmp	al, 1
	je .2
	pop	ax
	popf
	retn

BITS 32
waitesc32:
	pushfd
	push	eax
.1:	in	al, 60h
	cmp	al, 1
	jne .1
.2:	in	al, 60h
	cmp	al, 1
	je .2
	pop	eax
	popfd
	retn


BITS 32
ALIGN 4
int_00:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+0)*2
	mov	ax, 0x0F00 + '0'
	cld
	stosw
	mov	al, '0'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_01:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+4)*2
	mov	ax, 0x0F00 + '1'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_02:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+8)*2
	mov	ax, 0x0F00 + '2'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_03:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+12)*2
	mov	ax, 0x0F00 + '3'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_04:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+16)*2
	mov	ax, 0x0F00 + '4'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_05:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+20)*2
	mov	ax, 0x0F00 + '5'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_06:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+24)*2
	mov	ax, 0x0F00 + '6'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_07:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+28)*2
	mov	ax, 0x0F00 + '7'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_08:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+32)*2
	mov	ax, 0x0F00 + '0'
	stosw
	mov	al, '8'
	stosw
	inc	byte [es:edi]
	mov	al, 60h		; specific EOI for IRQ0
;	mov	al, 20h		; non-specific EOI
	out	20h, al
	pop	es
	popad
	iretd

ALIGN 4
int_09:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+36)*2
	mov	ax, 0x0F00 + '0'
	cld
	stosw
	mov	al, '9'
	stosw
	inc	byte [es:edi]
	mov	al, 61h		; specific EOI for IRQ1
;	mov	al, 20h		; non-specific EOI
	out	20h, al
	pop	es
	popad
	iretd

ALIGN 4
int_0A:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+40)*2
	mov	ax, 0x0F00 + 'A'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_0B:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+44)*2
	mov	ax, 0x0F00 + 'B'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_0C:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+48)*2
	mov	ax, 0x0F00 + 'C'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_0D:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+52)*2
	mov	ax, 0x0F00 + 'D'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_0E:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+56)*2
	mov	ax, 0x0F00 + 'E'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_0F:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+60)*2
	mov	ax, 0x0F00 + 'F'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_10:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+64)*2
	mov	ax, 0x0F00 + 'X'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_11:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+68)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, '1'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_12:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (16*80+72)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, '2'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_13:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+0)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, '3'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_14:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+4)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, '4'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_15:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+8)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, '5'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_16:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+12)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, '6'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_17:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+16)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, '7'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_18:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+20)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, '8'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_19:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+24)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, '9'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_1A:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+28)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, 'A'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_1B:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+32)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, 'B'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_1C:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+36)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, 'C'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_1D:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+40)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, 'D'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_1E:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+44)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, 'E'
	stosw
	pop	es
	popad
	iretd

ALIGN 4
int_1F:
	pushad
	push	es
	mov	ax,18h
	mov	es, ax
	mov	edi, (17*80+48)*2
	mov	ax, 0x0F00 + '1'
	cld
	stosw
	mov	al, 'F'
	stosw
	pop	es
	popad
	iretd

SEGMENT _DATA
ALIGN 2

msg_crlf:
	db 13,10
; real mode message table
	dw RMMSGCOUNT
rmmsgtab:
	dw .msg0
	dw .msg1
	dw .endtab
.msg0:	db 'Processor already in V86 mode.'
.msg1:	db 'DOS resize memory block failed.'
.endtab:


ALIGN 8
; SELECTOR FORMAT
;15                              8  7                 4  3  2      0
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+
; |                      INDEX                         |LDT|  DPL  |
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+
; 
; DESCRIPTOR FORMAT:
;
;15                              8  7                              0  BYTE
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+
; |       BASE 24-31              || G |D/B| L |AVL|  LIMIT 16-19  |
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+  +6
; | P |  DPL  | S |      TYPE     ||       BASE ADDRESS 16-23      |
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+  +4
; |                       BASE ADDRESS 0-15                        |
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+  +2
; |                           LIMIT 0-15                           |
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+   0
;
; TYPE field:
;  3             0
; +---+---+---+---+
; |C/D|   |   | A |  C/D=code/data; 1=code, 0=data.  A=accessed
; +---+---+---+---+
; | 0 | E | W | A |  E=expand down, W=write access
; +---+---+---+---+
; | 1 | C | R | A |  C=conforming, R=read access
; +---+---+---+---+

our_gdt:
	dd 0, 0		; entry 0: unused
.sel08: ; code segment selector (32-bit)
	dw 0xFFFF  ; +0  limit bits 0-15
	dw 0       ; +2  base addr. 0-15
	db 0       ; +4  base addr. 16-23
	db 0x9B    ; +5  PDdSType, *P=present, D=DPL, S=0=system descr. type
	db 0x40    ; +6  GBLALimt, G=gran., B=32bit, L=64bit-, A=avail.
	db 0       ; +7  base addr. 24-31
.sel10: ; data and stack segment selector (16-bit)
	dw 0xFFFF  ; +0  limit bits 0-15
	dw 0       ; +2  base addr. 0-15
	db 0       ; +4  base addr. 16-23
	db 0x93    ; +5  PDdSType, *P=present, D=DPL, S=0=sys.desc, d.seg+w
	db 0x00    ; +6  GBLALimt, G=gran., B=16bit*, L=64bit-, A=avail.
	db 0x00    ; +7  base addr. 24-31
.sel18: ; text mode VGA memory
	dw 0xFFF   ; +0  limit 4095
	dw 0x8000  ; +2  low 16 bits of base addr.
	db 0x0B    ; +4  bits 16-23 of base addr.
	db 0x93    ; +5  PDdSType, *P=present, D=DPL, S=0=sys.desc, d.seg+w
	db 0x00    ; +6  GBLALimt, G=gran., B=16bit*, L=64bit-, A=avail.
	db 0x00    ; +7  base addr. 24-31
.end:

ALIGN 8
; INTERRUPT GATE DESCRIPTOR FORMAT:
;
;15                              8  7                              0  BYTE
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+
; |                          OFFSET 16-31                          |
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+  +6
; | P |  DPL  |S=0| D   1   1   0 || 0   0   0 | -   -   -   -   - |
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+  +4
; |                            SELECTOR                            |
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+  +2
; |                           OFFSET 0-15                          |
; +---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---+   0
; D=size of gate; 1=32 bits.
our_idt:
.ent00:	dw int_00  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent01:	dw int_01  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent02:	dw int_02  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent03:	dw int_03  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent04:	dw int_04  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent05:	dw int_05  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent06:	dw int_06  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent07:	dw int_07  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent08:	dw int_08  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent09:	dw int_09  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent0A:	dw int_0A  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent0B:	dw int_0B  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent0C:	dw int_0C  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent0D:	dw int_0D  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent0E:	dw int_0E  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent0F:	dw int_0F  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent10:	dw int_10  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent11:	dw int_11  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent12:	dw int_12  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent13:	dw int_13  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent14:	dw int_14  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent15:	dw int_15  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent16:	dw int_16  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent17:	dw int_17  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent18:	dw int_18  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent19:	dw int_19  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent1A:	dw int_1A  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent1B:	dw int_1B  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent1C:	dw int_1C  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent1D:	dw int_1D  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent1E:	dw int_1E  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.ent1F:	dw int_1F  ; offset bits 0-15
	dw 0       ; selector
	db 0x00    ; bits 0-4 reserved, bits 5-7 must be 0
	db 0x8e    ; 32-bit interrupt gate
	dw 0       ; offset 16-31
.end:
	

SEGMENT .bss	; must be .bss not _BSS to make NASM understand
ALIGN 16
bss_starts:
	resw 4096	; 8192 bytes reserved for stack+BSS
stack_ends:

; vim: set syn=nasm:
