-saved_esp: .long 0
-saved_ebp: .long 0
-
- # drop back to unreal mode to call 16bit interrupt
- .global int86
-int86:
- push %ebp
- mov %esp, %ebp
- pushal
- cli
- # save protected mode IDTR and replace it with the real mode vectors
- sidt (saved_idtr)
- lidt (rmidt)
-
- # modify the int instruction do this here before the
- # cs-load jumps, to let them flush the instruction cache
- mov $int_op, %ebx
- movb 8(%ebp), %al
- movb %al, 1(%ebx)
-
- # long jump to load code selector for 16bit code (6)
- ljmp $0x30,$0f
-0:
- .code16
- # disable protection
- mov %cr0, %eax
- and $0xfffe, %ax
- mov %eax, %cr0
- # load cs <- 0
- ljmp $0,$0f
-0: # zero data segments
- xor %ax, %ax
- mov %ax, %ds
- mov %ax, %es
- mov %ax, %ss
- nop
-
- # load registers from the int86regs struct
- mov %esp, saved_esp
- mov %ebp, saved_ebp
- mov 12(%ebp), %esp
- popal
- popfw
- pop %es
- pop %ds
- # ignore fs and gs for now, don't think I'm going to need them
- mov saved_esp, %esp
-
- # call 16bit interrupt
-int_op: int $0
-
- mov saved_ebp, %ebp
- mov 12(%ebp), %esp
- add $38, %esp
- push %ds
- push %es
- pushfw
- pushal
- mov saved_esp, %esp
-
- # re-enable protection
- mov %cr0, %eax
- or $1, %ax
- mov %eax, %cr0
- # long jump to load code selector for 32bit code (1)
- ljmp $0x8,$0f
-0:
- .code32
- # set data selector (2) to all segment regs
- mov $0x10, %ax
- mov %ax, %ds
- mov %ax, %es
- mov %ax, %ss
- nop
-
- # restore 32bit interrupt descriptor table
- lidt (saved_idtr)
- sti
- popal
- pop %ebp
- ret
-
-