global clear_tss global switch_to global set_tss extern cstate extern ctask extern gdt extern save_state ; void switch_to(int n, struct task_struct *task); switch_to: push ebp mov ebp, esp ; abort if we're switching to the current task mov ebx, [ctask] cmp ebx, [ebp+12] jne .skip pop ebp ret .skip: ; clear the busy flag in the current TSS mov eax, 0 str ax add ax, gdt+5 mov byte [eax], 0x89 ; set the current TSS to null so it won't be overwritten by the switch mov ax, 0 ltr ax ; copy the saved state into the previous TSS call save_state ; update ctask mov ebx, [ebp+12] mov [ctask], ebx ; calculate the task segment index and jump to it mov ebx, [ebp+8] add ebx, 5 shl ebx, 3 mov [.tmp+4], bx jmp far [.tmp] .tmp: dq 0 ; void set_tss(unsigned int n, void *tss); set_tss: push ebp mov ebp, esp push ebx mov eax, [ebp+12] mov ebx, [ebp+8] shl ebx, 3 add ebx, gdt+40 mov [ebx+2], ax shr eax, 16 mov [ebx+4], al mov [ebx+7], ah mov eax, 103 ; limit - 1 mov [ebx], ax shr eax, 16 and al, 0x0F mov [ebx+6], al mov byte [ebx+5], 0x89 pop ebx pop ebp ret ; void clear_tss(unsigned int n); clear_tss: push ebp mov ebp, esp push ebx mov ebx, [ebp+8] shl ebx, 3 add ebx, gdt+40 mov byte [ebx+5], 0 pop ebx pop ebp ret