Linux内核完全注释(v0.11)--get_base()、get_limit()

参考:《Linux内核完全注释:基于0.11内核
该书下载地址:http://www.oldlinux.org/download/clk011c-3.0.pdf

阅读Linux内核完全注释traps.c,发现有个函数赵博士没有说明。好吧,自己动手丰衣足食。
traps.c里源码第72行是这样的:

printk("base: %p, limit: %p\n", get_base(current->ldt[1]), get_limit(0x17));

get_base()函数

这个get_base()函数在sched.h里定义的:

#define get_base(ldt) _get_base( ((char *)&(ldt)) )

...

#define _get_base(addr) ({\
unsigned long __base; \
__asm__("movb %3,%%dh\n\t" \
	"movb %2,%%dl\n\t" \
	"shll $16,%%edx\n\t" \
	"movw %1,%%dx" \
	:"=d" (__base) \
	:"m" (*((addr)+2)), \
	 "m" (*((addr)+4)), \
	 "m" (*((addr)+7))); \
__base;})

光看这个肯定是一头雾水。好在参数current->ldt[1]提供了线索。这个参数表示当前任务的代码段,这个可以从《Linux内核完全剖析:基于0.11内核v3.0》第132页看出。
Linux内核完全注释修正版v3.0第132页
既然是代码段了那当然要看一看段描述符通用格式,如图:
在这里插入图片描述
addr指向当前任务代码段字节0处,所以:
(addr)+2 ------ 上图第2行16-31位(指令是movw %1,%%dx,所以是16位);
(addr)+4 ------ 上图第1行0-7位(指令是movb %2,%%dl,所以是8位);
(addr)+7 ------ 上图第1行24-31位(指令是movb %3,%%dh,所以是8位)
所以整个过程就是把三个基地址片段组装成完整的段基地址存入edx寄存器

get_limit()函数

#define get_limit(segment) ({ \
unsigned long __limit; \
__asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \
__limit;})

lsll指令加载段限长。然后再加1作为返回值。
此外这个背后又是满满的一页…
0x17就是截图里的第四个例子
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值