zoukankan      html  css  js  c++  java
  • linux源代码阅读笔记 get_free_page()代码分析

    33 /*
     34  * Get physical address of first (actually last :-) free page, and mark it
     35  * used. If no free pages left, return 0.
     36  */
     37 unsigned long get_free_page(void)
     38 {
     39 register unsigned long __res asm("ax");
     40 
     41 __asm__("std ; repne ; scasw
    	"
     42         "jne 1f
    	"
     43         "movw $1,2(%%edi)
    	"        //将对应页面的内存映像置1(使用)
     44         "sall $12,%%ecx
    	"        //页面数*4kb=相对LOW_MEMORY的页面起始地址
    45 "movl %%ecx,%%edx "    //加上LOW_MEMORY形成物理起始地址 46 "addl %2,%%edx "       //页面实际地址给edx 47 "movl $1024,%%ecx " 48 "leal 4092(%%edx),%%edi " //将该页面的末端地址给edi 49 "rep ; stosl " //将edi所指内存请0 50 "movl %%edx,%%eax " 51 "1:" 52 :"=a" (__res) 53 :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES), 54 "D" (mem_map+PAGING_PAGES-1) 55 :"di","cx","dx"); 56 return __res; 57 }

    这段代码的作用是获取一个空闲的内存页,并且返回它的地址。

    首先分析,std ; repne ;scasw 这三句的作用。首先,我们参考一下下面这这篇文章:http://blog.163.com/b____d/blog/static/7491166020099115207391/

    那么,我们来分析一下这个函数里含义。首先,在这三句代码执行以前,asm已经将参数装入寄存器。即:

    %1(ax=0) %2(LOW_MEM)  %3(cx=PAGING_PAGES)  %4(edi=mem_map+PAGING_PAGES-1) 。这里注意的是,参数%1 "0" (0),”0“表示使用和输出相同的寄存器。即eax。

    这样,这三句话的含义就很清楚了,它的作用是从edi指代的地址搜索,如果找到0位,则返回。直到检索了PAGING_PAGES长度。

    也就是说,这三句指令在mem_map[ ]数组中寻找0位,并且该0位的index存储在edx中。

    疑问:系统页面长度为4096bit,为何将页面内容清0时,赋予计数器ecx的值是1024而不是4096?

    答:关注这里的清零指令,rep;stosl

      STOSL指令相当于将EAX中的值保存到ES:EDI指向的地址中,若设置了EFLAGS中的方向位置位(即在STOSL指令前使用STD指令)则EDI自减4,否则(使用CLD指令)EDI自增4。

      由此可见,stosl每次将4个bit清零。因此计数器赋值1024。同理,这样是为什么edi的初始值被赋予4092而不是4095

  • 相关阅读:
    有哪些命令行的软件堪称神器?
    [置顶] 《技术大牛养成指南》
    Java 8 集合不完全一览
    [置顶] tcpflow 抓包
    被遗忘的 Logrotate
    [置顶] Every Programmer Should Know These Latency Numbers
    安装 Ubuntu 14.04 之后要做的一些事
    windows.h系统函数
    《葡萄源》
    在 Visual Studio 中创建一个简单的 C# 控制台应用程序
  • 原文地址:https://www.cnblogs.com/elnino/p/4432146.html
Copyright © 2011-2022 走看看