Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- [bits 32]
- global int32, _int32
- struc regs16_t
- .di resw 1
- .si resw 1
- .bp resw 1
- .sp resw 1
- .bx resw 1
- .dx resw 1
- .cx resw 1
- .ax resw 1
- .gs resw 1
- .fs resw 1
- .es resw 1
- .ds resw 1
- .ef resw 1
- endstruc
- %define INT32_BASE 0x7C00
- %define REBASE(x) (((x) - reloc) + INT32_BASE)
- %define GDTENTRY(x) ((x) << 3)
- %define CODE32 GDTENTRY(1) ; 0x08
- %define DATA32 GDTENTRY(2) ; 0x10
- %define CODE16 GDTENTRY(3) ; 0x18
- %define DATA16 GDTENTRY(4) ; 0x20
- %define STACK16 (INT32_BASE - regs16_t_size)
- section .text
- int32: use32 ; by Napalm
- _int32:
- pushf ; Save flags (including interrupt flag)
- cli ; disable interrupts
- pusha ; save register state to 32bit stack
- mov esi, reloc ; set source to code below
- mov edi, INT32_BASE ; set destination to new base address
- mov ecx, (int32_end - reloc) ; set copy size to our codes size
- cld ; clear direction flag (so we copy forward)
- rep movsb ; do the actual copy (relocate code to low 16bit space)
- jmp INT32_BASE ; jump to new code location
- reloc: use32 ; by Napalm
- mov [REBASE(stack32_ptr)], esp ; save 32bit stack pointer
- sidt [REBASE(idt32_ptr)] ; save 32bit idt pointer
- sgdt [REBASE(gdt32_ptr)] ; save 32bit gdt pointer
- lgdt [REBASE(gdt16_ptr)] ; load 16bit gdt pointer
- lea esi, [esp+0x24] ; set position of intnum on 32bit stack
- lodsd ; read intnum into eax
- mov [REBASE(ib)], al ; set intrrupt immediate byte from our arguments
- mov esi, [esi] ; read regs pointer in esi as source
- mov edi, STACK16 ; set destination to 16bit stack
- mov ecx, regs16_t_size ; set copy size to our struct size
- mov esp, edi ; save destination to as 16bit stack offset
- rep movsb ; do the actual copy (32bit stack to 16bit stack)
- jmp word CODE16:REBASE(p_mode16) ; switch to 16bit selector (16bit protected mode)
- p_mode16: use16
- mov ax, DATA16 ; get our 16bit data selector
- mov ds, ax ; set ds to 16bit selector
- mov es, ax ; set es to 16bit selector
- mov fs, ax ; set fs to 16bit selector
- mov gs, ax ; set gs to 16bit selector
- mov ss, ax ; set ss to 16bit selector
- mov eax, cr0 ; get cr0 so we can modify it
- and al, ~0x01 ; mask off PE bit to turn off protected mode
- mov cr0, eax ; set cr0 to result
- jmp word 0x0000:REBASE(r_mode16) ; finally set cs:ip to enter real-mode
- r_mode16: use16
- xor ax, ax ; set ax to zero
- mov ds, ax ; set ds so we can access idt16
- mov ss, ax ; set ss so they the stack is valid
- lidt [REBASE(idt16_ptr)] ; load 16bit idt
- mov bx, 0x0870 ; master 8 and slave 112
- call resetpic ; set pic's the to real-mode settings
- popa ; load general purpose registers from 16bit stack
- pop gs ; load gs from 16bit stack
- pop fs ; load fs from 16bit stack
- pop es ; load es from 16bit stack
- pop ds ; load ds from 16bit stack
- ; enable interrupts
- db 0xCD ; opcode of INT instruction with immediate byte
- ib: db 0x00
- cli ; disable interrupts
- xor sp, sp ; zero sp so we can reuse it
- mov ss, sp ; set ss so the stack is valid
- mov sp, INT32_BASE ; set correct stack position so we can copy back
- pushf ; save eflags to 16bit stack
- push ds ; save ds to 16bit stack
- push es ; save es to 16bit stack
- push fs ; save fs to 16bit stack
- push gs ; save gs to 16bit stack
- pusha ; save general purpose registers to 16bit stack
- mov bx, 0x2028 ; master 32 and slave 40
- call resetpic ; restore the pic's to protected mode settings
- mov eax, cr0 ; get cr0 so we can modify it
- inc eax ; set PE bit to turn on protected mode
- mov cr0, eax ; set cr0 to result
- jmp dword CODE32:REBASE(p_mode32) ; switch to 32bit selector (32bit protected mode)
- p_mode32: use32
- mov ax, DATA32 ; get our 32bit data selector
- mov ds, ax ; reset ds selector
- mov es, ax ; reset es selector
- mov fs, ax ; reset fs selector
- mov gs, ax ; reset gs selector
- mov ss, ax ; reset ss selector
- lgdt [REBASE(gdt32_ptr)] ; restore 32bit gdt pointer
- lidt [REBASE(idt32_ptr)] ; restore 32bit idt pointer
- mov esp, [REBASE(stack32_ptr)] ; restore 32bit stack pointer
- mov esi, STACK16 ; set copy source to 16bit stack
- lea edi, [esp+0x28] ; set position of regs pointer on 32bit stack
- mov edi, [edi] ; use regs pointer in edi as copy destination
- mov ecx, regs16_t_size ; set copy size to our struct size
- cld ; clear direction flag (so we copy forward)
- rep movsb ; do the actual copy (16bit stack to 32bit stack)
- popa ; restore registers
- popf ; Restore interrupts
- ret ; return to caller
- resetpic: ; reset's 8259 master and slave pic vectors
- push ax ; expects bh = master vector, bl = slave vector
- mov al, 0x11 ; 0x11 = ICW1_INIT | ICW1_ICW4
- out 0x20, al ; send ICW1 to master pic
- out 0xA0, al ; send ICW1 to slave pic
- mov al, bh ; get master pic vector param
- out 0x21, al ; send ICW2 aka vector to master pic
- mov al, bl ; get slave pic vector param
- out 0xA1, al ; send ICW2 aka vector to slave pic
- mov al, 0x04 ; 0x04 = set slave to IRQ2
- out 0x21, al ; send ICW3 to master pic
- shr al, 1 ; 0x02 = tell slave its on IRQ2 of master
- out 0xA1, al ; send ICW3 to slave pic
- shr al, 1 ; 0x01 = ICW4_8086
- out 0x21, al ; send ICW4 to master pic
- out 0xA1, al ; send ICW4 to slave pic
- pop ax ; restore ax from stack
- ret ; return to caller
- stack32_ptr: ; address in 32bit stack after we
- dd 0x00000000 ; save all general purpose registers
- idt32_ptr: ; IDT table pointer for 32bit access
- dw 0x0000 ; table limit (size)
- dd 0x00000000 ; table base address
- gdt32_ptr: ; GDT table pointer for 32bit access
- dw 0x0000 ; table limit (size)
- dd 0x00000000 ; table base address
- idt16_ptr: ; IDT table pointer for 16bit access
- dw 0x03FF ; table limit (size)
- dd 0x00000000 ; table base address
- gdt16_base: ; GDT descriptor table
- .null: ; 0x00 - null segment descriptor
- dd 0x00000000 ; must be left zero'd
- dd 0x00000000 ; must be left zero'd
- .code32: ; 0x01 - 32bit code segment descriptor 0xFFFFFFFF
- dw 0xFFFF ; limit 0:15
- dw 0x0000 ; base 0:15
- db 0x00 ; base 16:23
- db 0x9A ; present, iopl/0, code, execute/read
- db 0xCF ; 4Kbyte granularity, 32bit selector; limit 16:19
- db 0x00 ; base 24:31
- .data32: ; 0x02 - 32bit data segment descriptor 0xFFFFFFFF
- dw 0xFFFF ; limit 0:15
- dw 0x0000 ; base 0:15
- db 0x00 ; base 16:23
- db 0x92 ; present, iopl/0, data, read/write
- db 0xCF ; 4Kbyte granularity, 32bit selector; limit 16:19
- db 0x00 ; base 24:31
- .code16: ; 0x03 - 16bit code segment descriptor 0x000FFFFF
- dw 0xFFFF ; limit 0:15
- dw 0x0000 ; base 0:15
- db 0x00 ; base 16:23
- db 0x9A ; present, iopl/0, code, execute/read
- db 0x0F ; 1Byte granularity, 16bit selector; limit 16:19
- db 0x00 ; base 24:31
- .data16: ; 0x04 - 16bit data segment descriptor 0x000FFFFF
- dw 0xFFFF ; limit 0:15
- dw 0x0000 ; base 0:15
- db 0x00 ; base 16:23
- db 0x92 ; present, iopl/0, data, read/write
- db 0x0F ; 1Byte granularity, 16bit selector; limit 16:19
- db 0x00 ; base 24:31
- gdt16_ptr: ; GDT table pointer for 16bit access
- dw gdt16_ptr - gdt16_base - 1 ; table limit (size)
- dd gdt16_base ; table base address
- int32_end: ; end marker (so we can copy the code)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement