__asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
return current
将esp与8191ul做与运算。
tss与任务的内核堆栈在连续的两个页内,同时被分配。
---------esp/ebp
4k
---------------------- 页A
4k
---------end of tss
---------begin of tss 页B
图1.
将esp减去8k即可得到tss的起始地址。
而处于效率考虑,将esp与0xFFFFE000作and也可得到同样的效果。
~8191ul=0xFFFFE000
(ul=unsigned long)
~8191=1111 1111 1111 1111 1110 0000 0000 0000
8191=00001FFF=0000 0000 0000 0000 0001 1111 1111 1111
~8191=1111 1111 1111 1111 1110 0000 0000 0000=FFFFE000
~表示求反码
%%esp and $0xFFFFE000
因为在分页机制下,任何页的起始地址均为形如xxxxx000h,即最后12位为0,高20位视作
页号。
如图1,将esp后12位置0(与000作与操作)则得到页A的起始地址,将页A的页号减1(页号最后一位置0,即页号xxxxxh与FFFFEh做与操作=FFFFEh-1),则得到页B的起始地址即tss的起始地址。
所以将esp最后13位置0,可得tss起始地址。