extern _inline void switch_to(int n)
{
unsigned short __tmp;
__tmp = (unsigned short)_TSS(n);
_asm {
mov ebx, offset task
mov eax, n
mov ecx, [ebx+eax*4]
cmp ecx, current/* 任务n 是当前任务吗?(current ==task[n]?) */
je l1 /* 是,则什么都不做,退出。*/
xchg ecx,current/* current = task[n]; */
/*执行长跳转,造成任务切换 (头大了很长时间,多多包涵)*/
mov ax, __tmp
mov word ptr ds:[lcs],ax
_emit 0xea
_emit 0 // ip
_emit 0
_emit 0
_emit 0
lcs: _emit 0 // cs
_emit 0
// 在任务切换回来后才会继续执行下面的语句。
cmp last_task_used_math,ecx /* 新任务上次使用过协处理器吗?*/
jne l1
clts/* 新任务上次使用过协处理器,则清cr0 的TS 标志。*/
}
l1: ;
}
上面这段函数就是linux用来切换任务的函数。
刚开始阅读时,对红色的这段非常不理解。
在查阅了一些资料后,终于恍然大悟
资料:
jmp far F000:E05B 翻成机器 码就是 0xEA 0x5B 0xE0 0x00 0xF0
_emit指令就是直接将后面的1字节内容输出。
根据资料,我就知道了
_emit 0xEA就是jmp
紧跟在jmp后面的4字节就是IP(偏移值),再接下来的2字节就是段选择符。
mov word ptr ds:[lcs],ax。就是将ax的内容移动到上面提到的cs中,而此时ax内的内容就是tss中当前任务的cs值