dynamic far call in 32-bit protected mode
Posted: Mon Aug 31, 2015 1:12 pm
Hello all,
I'm writing a kernel that uses hardware task switching. To call a task, I need to do a far call to the TSS descriptor of the task (each task has a TSS descriptor in the GDT).
For example, to run task1, one would write:
For task2 (provided it's the next descriptor in the GDT), it would be:
and so on...
It's totally unflexible and I don't want to hardcode the segment selector. It needs to by dynamic. Ideally, it should be something like this, where the argument is the task selector of the task we want to call:
However, such code is not permitted. Therefore, I thought of writing some self-modifying code to change the segment descriptor, like this:
Basically, I store cs into ds in order to be able to reference the .selfmod label. Then, I modify the 16-bit data located 4 dword further to the value of the selector passed in argument.
However, it doesn't work.
I suspect the way I get the address of the .selfmod label is not correct.
Does anyone have an idea how I can write a version of my call_task where the code would do a far jump to the selector passed in argument?
Thanks a lot!
I'm writing a kernel that uses hardware task switching. To call a task, I need to do a far call to the TSS descriptor of the task (each task has a TSS descriptor in the GDT).
For example, to run task1, one would write:
Code: Select all
call_task1:
call 0x20:0
ret
Code: Select all
call_task1:
call 0x28:0
ret
It's totally unflexible and I don't want to hardcode the segment selector. It needs to by dynamic. Ideally, it should be something like this, where the argument is the task selector of the task we want to call:
Code: Select all
call_task:
call [esp+4]:0
ret
Code: Select all
call_task:
; Opcodes for the far call 0x1234:0x2694
; 9a 94 26 00 00 34 12 lcall $0x1234,$0x2694
push ebp
mov ebp,esp
push ds
push ebx
push eax
mov bx,cs
mov ds,bx
mov dword ebx,(.selfmod+4)
mov ax,[ebp+8]
mov word [ebx],ax ; change the 0xFF below to the contents of AX
pop eax
pop ebx
pop ds
pop ebp
.selfmod:
call 0xFF:0
ret
However, it doesn't work.
I suspect the way I get the address of the .selfmod label is not correct.
Does anyone have an idea how I can write a version of my call_task where the code would do a far jump to the selector passed in argument?
Thanks a lot!