summaryrefslogtreecommitdiff
path: root/rt/+x86_64/realcall.S
diff options
context:
space:
mode:
Diffstat (limited to 'rt/+x86_64/realcall.S')
-rw-r--r--rt/+x86_64/realcall.S74
1 files changed, 51 insertions, 23 deletions
diff --git a/rt/+x86_64/realcall.S b/rt/+x86_64/realcall.S
index 46745f8..9e9afb4 100644
--- a/rt/+x86_64/realcall.S
+++ b/rt/+x86_64/realcall.S
@@ -1,7 +1,7 @@
.code64
-.globl real.regs
-real.regs:
+.globl bios.regs
+bios.regs:
reax:
.int 0x0
rebx:
@@ -14,6 +14,17 @@ redi:
.int 0x0
resi:
.int 0x0
+rds:
+ .short 0x0
+res:
+ .short 0x0
+rss:
+ .short 0x0
+rgs:
+ .short 0x0
+rfs:
+ .short 0x0
+
# :real_call
@@ -26,9 +37,9 @@ resi:
# above.
# The procedure to go from Long Mode back to Real Mode is explained in much details
# in the AMD64 Programmer's Manual Vol. 2, in particular, the figure 1-6. in section 1.3.
-.globl real.call
-real.call:
- # :Push all the segments registers
+.globl bios.call
+bios.call:
+ xchg %bx, %bx
push %rbx
push %r12
push %r13
@@ -80,27 +91,44 @@ real_call_to_16bits_rmode_down:
mov %ax, %gs
mov %ax, %fs
- # :real mode, yay
-
lidt bios_idtr
-
sti
- mov rebx, %ebx
- mov recx, %ecx
- mov redx, %edx
- mov redi, %edi
- mov resi, %esi
-
- pop %ax
- call *%ax
-
- mov %eax, reax
- mov %ebx, rebx
- mov %ecx, recx
- mov %edx, redx
- mov %edi, redi
- mov %esi, resi
+ # :Self modifying code to call arbitrary interrupts
+ pop %ax
+ mov $real_call_int, %bx
+ mov %al, 1(%bx)
+
+ push %ds
+
+ # :Load registers
+ mov (reax), %eax
+ mov (rebx), %ebx
+ mov (recx), %ecx
+ mov (redx), %edx
+ mov (redi), %edi
+ mov (resi), %esi
+ mov %ds:(res), %es
+ mov %ds:(rss), %ss
+ mov %ds:(rgs), %gs
+ mov %ds:(rfs), %fs
+ mov %ds:(rds), %ds
+ xchg %bx, %bx
+
+real_call_int:
+ int $0x0
+
+ pop %ds
+ mov %ds:(rfs), %fs
+ mov %ds:(rgs), %gs
+ mov %ds:(rss), %ss
+ mov %ds:(res), %es
+ mov %eax, (reax)
+ mov %ebx, (rebx)
+ mov %ecx, (recx)
+ mov %edx, (redx)
+ mov %edi, (redi)
+ mov %esi, (resi)
cli