I have a fully functional IDT code(also ISR, IRQ,...) written in C/C++. But I wanted to make things more simple, and transparent, so I decided to rewrite my IDT code in assembly. As I did with the GDT code.
The matter is that my exceptions are in a different file and are defined as a macro in order to avoid repeating code.
The procedures found in the file are:
- __install_gate -> Sets a descriptor gate
- __set_gates -> Sets all of 32 exceptions gates for the IDT.
- __install_idt -> Calls __set_gates and then loads the address into IDTR
- 1. Set gates and load IDT
- 2. Force exception(i.e. by-zero div.)
- 3. Page Fault is called, cannot call any handler because IDT seems corrupt.
- 4. After second PF, which is the third raised exception, Triple Fault and reset.
Below the full code:
Code: Select all
.section .text
.global __install_idt
/*
* EAX: idt array index
* EBX: idt array start
*
* ECX: offset
* DX: segment selector
* DI: flags
*/
__install_gate:
push %eax
push %ebx
push %ecx
push %edx
push %esi
push %edi
mov %eax, %esi
mov _idt_gate_start, %ebx
//offset low 16 and high 16
mov %ecx, %eax
mov %ax, 0(%ebx, %esi, 8)
shr $16, %eax
mov %ax, 6(%ebx, %esi, 8)
//segment selector
mov %dx, 2(%ebx, %esi, 8)
//flags and zeroed
shl $8, %edi
and $0xFF00, %edi
mov %di, 4(%ebx, %esi, 8)
pop %edi
pop %esi
pop %edx
pop %ecx
pop %ebx
pop %eax
ret
__set_gates:
push %eax
push %ebx
push %ecx
push %edx
push %edi
push %esi
mov $32, %ecx
__idt_spec_set:
mov _idt_start, %ebx
mov $_KERNEL_CS, %edx
xor %edi,%edi
mov $_IDT_GATE_FLAGS, %di
//no need to modify ecx?
push %ecx
mov $_exceptions_table, %esi # address of table
#mov (%esi), %eax
#mov %eax, %esi
dec %ecx
mov %ecx, %eax #index in table
mov (%esi, %ecx, 4),%ecx # macro label address in table
#mov (%ecx), %ecx # address of function
call __install_gate
pop %ecx
loop __idt_spec_set
/*
mov $0x00008E0000080000, %eax
mov _idt_start, %ebx
mov %ea
*/
pop %esi
pop %edi
pop %edx
pop %ecx
pop %ebx
pop %eax
ret
__install_idt:
call __set_gates
#cli
lidtl _idtr
#sti
ret
.section .data
_idtr:
.word (_idt_end - _idt_start)
.long _idt_start
_idt_start:
.space (_IDT_GATE_SIZE * 256)
_idt_end:
_exceptions_table:
.long __int_0x00
.long __int_0x01
.long __int_0x02
.long __int_0x03
.long __int_0x04
.long __int_0x05
.long __int_0x06
.long __int_0x07
.long __int_error_0x08
.long __int_0x09
.long __int_error_0x0A
.long __int_error_0x0B
.long __int_error_0x0C
.long __int_error_0x0D
.long __int_error_0x0E
.long __int_0x0F
.long __int_0x10
.long __int_error_0x11
.long __int_0x12
.long __int_0x13
.long __int_0x14
.long __int_0x15
.long __int_0x16
.long __int_0x17
.long __int_0x18
.long __int_0x19
.long __int_0x1A
.long __int_0x1B
.long __int_0x1C
.long __int_0x1D
.long __int_error_0x1E
.long __int_0x1F
.section .bss
_idt_gate_start:
offset1 : .space 2
segsec : .space 2
reserved : .space 1
p_dpl_0_gate : .space 1
offset2 : .space 2
_idt_gate_end:
.set _IDT_GATE_SIZE, (_idt_gate_end - _idt_gate_start)
.set _KERNEL_CS, 0x08
.set _IDT_GATE_FLAGS, 0x8E
Code: Select all
.section .text
.macro __int_ num
.global __int_\num
__int_\num:
cli
mov $\num, (_int_number)
push $0
push (_int_number)
jmp __int_common
.endm
.macro __int_error_ num
.global __int_error_\num
__int_error_\num:
cli
movb $\num, (_int_number)
push (_int_number)
jmp __int_common
.endm
__int_common:
//pushed EFLAGS, CS, EIP
//pushed error, int number
//push general purpose register
pushal
//push segments registers
push %ds
push %es
push %fs
push %gs
//clear df for c++ func
cld
push %esp
call __isr_handler
add $4, %esp
pop %gs
pop %fs
pop %es
pop %ds
popal
//discard int number and error code
add $8, %esp
iret
__int_ 0x00
__int_ 0x01
__int_ 0x02
__int_ 0x03
__int_ 0x04
__int_ 0x05
__int_ 0x06
__int_ 0x07
__int_error_ 0x08
__int_ 0x09
__int_error_ 0x0A
__int_error_ 0x0B
__int_error_ 0x0C
__int_error_ 0x0D
__int_error_ 0x0E
__int_ 0x0F
__int_ 0x10
__int_error_ 0x11
__int_ 0x12
__int_ 0x13
__int_ 0x14
__int_ 0x15
__int_ 0x16
__int_ 0x17
__int_ 0x18
__int_ 0x19
__int_ 0x1A
__int_ 0x1B
__int_ 0x1C
__int_ 0x1D
__int_error_ 0x1E
__int_ 0x1F
.section .bss
_int_number: .space 1