zoukankan      html  css  js  c++  java
  • 计算机器内存数量+引入和显示ARDS成员

    【1】README

    • 1.1) 本代码在于读取内存中多个 内存段的地址范围描述符结构体(ARDS),有多少个内存段可以用;
    • 1.2) source code and images in the blog from orange’s implemention of a os
    • 1.3) the comments towards code are built by myself , which proves to be a key point ,in my opinion.
    • 1.4) for complete code , please visit https://github.com/pacosonTang/Orange-s-OS/blob/master/p75.asm
    • Other)要知道,os 必须要知道内存的内容,以便进行内存管理。

    ##**【2】source code** * **2.1)得到内存数**
    	; 得到内存数 begin 
    	 mov	ebx, 0
    	 mov	di, _MemChkBuf ; _MemChkBuf: times	256	db	0, 缓冲区
    	.loop:
    	 mov	eax, 0E820h
    	 mov	ecx, 20
    	 mov	edx, 0534D4150h
    	 int	15h ; 每次中断,都把内存数据(不同内存段的描述和大小) copy 到 缓冲区_MemChkBuf中,
    	 jc	LABEL_MEM_CHK_FAIL ; jump if carry(CF=1), cf=0表示读取内存信息没有错误
    	 add	di, 20	; es:di 指向一个地址范围描述符结构 ARDS
    	 inc	dword [_dwMCRNumber]; _dwMCRNumber: dd	0	; Memory Check Result
    	 cmp	ebx, 0	; ebx 存储着下一个地址描述符所需要的后续值;
    	 jne	.loop
    	 jmp	LABEL_MEM_CHK_OK
    	LABEL_MEM_CHK_FAIL:
    	 mov	dword [_dwMCRNumber], 0
    	LABEL_MEM_CHK_OK:
    	
    	 ; 得到内存数 over
    
    • 代码步骤

      • step1)每次中断,都把不同内存段的 地址范围描述符结构体 copy 到 缓冲区_MemChkBuf中(连续地址),而缓冲区有256Bytes,而结构体有20B,所以只能copy 12个 结构体;copy完后,以便进行数据分析;
      • step2)如果内存段的 ARDS 没有读取出错的话,那么就将 内存数变量_dwMCRNumber 自加1 ;
    • Conclusion:(干货)
      每次中断,都把不同内存段的 地址范围描述符结构体 copy 到 缓冲区_MemChkBuf中,显然,整个内存是分为多个内存段的,然后内存段是由地址范围描述符结构体(ARDS)来描述的。
      这里写图片描述
      (由图知:ARDS的size=20Bytes)
      这里写图片描述

    • 2.2)读取内存数据并显示

        ; call	DispMemSize; 由保护模式的 显示内存信息 跳转到这里
        DispMemSize:
         push	esi
         push	edi
         push	ecx
        ; _MemChkBuf: times	256	db	0
        ; MemChkBuf equ	_MemChkBuf	- $$
        ; $$ == LABEL_DATA
         mov	esi, MemChkBuf ; 他就是 存放内存描述符结构体 的 缓冲区,共256个字节,每个结构体=20字节,所以最多存放12个结构体
        ; _ARDStruct:	 ; Address Range Descriptor Structure 地址范围描述符结构体
        ;	_dwBaseAddrLow:	 dd	0 基地址低32位
        ;	_dwBaseAddrHigh:	dd	0 基地址高32位
        ;	_dwLengthLow:	 dd	0 长度的低32位
        ;	_dwLengthHigh:	 dd	0 长度的高32位
        ;	_dwType:	 dd	0 这个地址范围的地址类型
        
         mov	ecx, [dwMCRNumber]; 外循环 for(int i=0;i<[MCRNumber];i++)//每次得到一个ARDS , line_113已经得到其内存数了,cur_line_328,
        .loop:	  ;{ loop 的循环数 == ecx ,上行代码已经赋值
         mov	edx, 5	  ;  内循环 for(int j=0;j<5;j++) //每次得到一个ARDS中的成员
        
        ; ARDStruct	 equ	_ARDStruct	- $$
        ; dwBaseAddrLow	 equ	_dwBaseAddrLow	- $$
        ; dwBaseAddrHigh	 equ	_dwBaseAddrHigh	- $$
        ; dwLengthLow	 equ	_dwLengthLow	- $$
        ; dwLengthHigh	 equ	_dwLengthHigh	- $$
        ; dwType	 equ	_dwType	 - $$
         mov	edi, ARDStruct	  ;  {//依次显示BaseAddrLow,BaseAddrHigh,LengthLow,
        .1:	  ;             LengthHigh,Type
         push	dword [esi]	  ; cur_line_343, line_318 mov	esi, MemChkBuf,offset=esi,esi += 4;
                ; line_113在计算内存数时,已经将全部ARDS copy 到 缓冲区了
                
         call	DispInt	  ; DispInt(MemChkBuf[j*4]); // 显示一个成员
         pop	eax	  	  ; 将偏移地址 弹出到 eax
                ; cur_line_347, line_340: mov	edi, ARDStruct
                
         stosd	  ; ARDStruct[j*4] = MemChkBuf[j*4]; eax copy到 edi 指向的目的地址(ARDStruct)
                ; 为什么要吧内存段描述符结构体从缓冲区copy到ARDS暂存呢?因为下面代码要用到变量:dwType + dwBaseAddrLow + dwLengthLow
         add	esi, 4	  	  ;	cur_line_348, line_318 mov	esi, MemChkBuf (256个0的内存空间的偏移地址)
         dec	edx	  ; edx == 总循环次数(5--)
         cmp	edx, 0	  	  ;
         jnz	.1	  	  ;  } 就这样循环下去吧,直到为0为止;
         call	DispReturn	  ;  printf("
      ");
         cmp	dword [dwType], 1 ;  if(Type == AddressRangeMemory)(该段内存可用的话) , 此刻的 dwType 是由line_349从缓冲区写入的,cur_line_357;
         jne	.2	  ;  {	  ;  如果该内存不可用的话,跳转到 .2;
         mov	eax, [dwBaseAddrLow]; 基地址的低32位
         add	eax, [dwLengthLow]  ; 长度的低32位
         cmp	eax, [dwMemSize]  ;    if(BaseAddrLow + LengthLow > MemSize-内存大小),MemSize初始化为0;求最大内存范围值
         jb	.2	  	  ; jb:无符号小于则跳转
                ; _dwMemSize:	 dd	0
                ; dwMemSize	 equ	_dwMemSize	- $$
         mov	[dwMemSize], eax  ;    MemSize = BaseAddrLow + LengthLow;
        .2:	  ;  } ; Type==AddressRangeReserved (该段内存不可用的话)
         loop	.loop	  ;}
              ;
         call	DispReturn	  ;printf("
      ");
         push	szRAMSize	  ; _szRAMSize	 db	"RAM size:", 0 ;字符串以 0 结尾
         call	DispStr	  ;printf("RAM size:");
         add	esp, 4	  ;
              ;
         push	dword [dwMemSize] ;
         call	DispInt	  ;DispInt(MemSize);
         add	esp, 4	  ;
        
         pop	ecx
         pop	edi
         pop	esi
         ret
      

    * **代码步骤:****(干货)** * **step1)**首先要知道,上一段代码已经算出了内存段(块)的个数 dwMCRNumber 和 吧 内存各个ARDS copy 到了缓冲区MemChkBuf中,我们这里的代码需要用这个个数 dwMCRNumber 和这个 存储有 各个 ARDS 数据的缓冲区MemChkBuf; * **step2)**通过双循环,读取每个ARDS的各个成员的值并打印,外循环个数为内存段(块)个数,内循环个数=5(因为ARDS有5个成员), 并将缓冲区中每个 ARDS 暂存在 ARDS结构中,以便下面代码取变量值; * **step3)**继续说循环,内循环结束后,比较dwType(内存块类型),判断该内存段是否可用,不可用,进入下一次外循环;若可用,继续判断dwBaseAddrLow(基地址的低32位) + dwLengthLow(长度的低32位) 是否大于最大内存地址dwMemSize, 总之dwMemSize 取 它们和的最大值;外循环ending * **step4)**最后打印出 最大内存地址 dwMemSize;
  • 相关阅读:
    优化后的 google提供的汉字转拼音类(针对某些htc等手机的不兼容情况)
    运行期可以变动大小和尺寸的自定义控件、
    123
    动态创建Ⅱ
    动态创建Ⅰ
    delphi XE5皮肤的使用
    ActionBar
    zhizhensuibi---Source aplikasi database dengan delphi7
    chadang saidui
    30yong wanquan
  • 原文地址:https://www.cnblogs.com/pacoson/p/4815297.html
Copyright © 2011-2022 走看看