日期:2014-05-16 浏览次数:20879 次
实现在swap.c 里面
程序功能概述:
首先在内存映射字节位图中查找值为0的字节项,然后把对应物理内存页面清零,如果得到的页面地址值大于实际物理内存容量则重新寻找。如果没有找到空闲页面则去调用执行交换处理,并重新查找。最后返回空闲物理地址。
我一开始没能比较熟练的掌握嵌入式汇编,所以又把问题的难度拔高了。。。如果熟练的掌握嵌入式汇编的话,不至于被卡这么久
:"=a" (__res)
:"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
"D" (mem_map+PAGING_PAGES-1)
:"di","cx","dx");
这里把输出寄存器指定为%eax, 并保存到变量__res中。返回是%0,这个是指令操作数,%0 代表 第一个占位符,即上面“=a” ax寄存器
%1 %2 %3 %4 分别代表代表 ax di cx dx 寄存器
输入
%1(ax = 0) -0
%2 (LOW_MEM) 这里并不是指定到di寄存器,“i”是说明这是个直接操作数。 这个定义为0x1000 是pg0 的起始位置。《注释》书上说“内存字节位图管理的起始位置” 这里有点小含糊,我郁闷了好一会儿,各种发帖子问。。。各种纠结其实我觉得这么描述不是很好,为啥不直接了当的很直白的说这里是mem_map第一个元素对应的内存页捏?我还以为mem_map就放在0x1000。mem_map是个全局变量,是不会放在0x1000的
%3 ecx = PAGING_PAGES
%4 edi = mem_map+PAGING_PAGES-1 这其实是mem_map最后一个元素的地址
限定符 | 意义 |
"m"、"v"、"o" | 内存单元 |
"r" | 任何寄存器 |
"q" | 寄存器eax、ebx、ecx、edx之一 |
"i"、"h" | 直接操作数 |
"E"和"F" | 浮点数 |
"g" | 任意 |
"a"、"b"、"c"、"d" | 分别表示寄存器eax、ebx、ecx和edx |
"S"和"D" | 寄存器esi、edi |
"I" | 常数(0至31) |
对于这些输入输出寄存器一定要理解好
"std ; repne ; scasb\n\t"
这行代码的作用是“置为方向,al(0) 与对应每个页面的di 做比较”
个人觉得,这句话,不要纠结。。。知道它真正做了什么就OK了。
这行代码会查询edi寄存器储存的地址处的值是否为0,每次循环(repeat 一次)
判断是否为0"jne 1f\n\t" 如果不是0,就跳转到嵌入式汇编结束的位置
如果是,执行跳转指令后面的
unsigned long get_free_page(void) { register unsigned long __res asm("ax"); repeat: __asm__("std ; repne ; scasb\n\t"//执行完scasb之后ecx - 1, edi -1 "jne 1f\n\t"//如果在mem_map里没有知道值为0的数组元素,即代表free page的位。那么这个时候所有的页都处于占用状态,get free page 第一次失败 "movb $1,1(%%edi)\n\t"//如果找到了空闲页,那么执行这指令,然后把该页对应页面内存映像比