【操作系统真象还原】第5章:保护模式进阶,向内核迈进(5.1获取物理内存)

目录

5.1 获取物理内存容量

5.1.1 学习 Linux 获取内存的方法

5.1.2 利用 BIOS中断 0x15 子功能 0xe820 获取内存

5.1.3 利用BIOS中断 0x15 子功能 0xe801 获取内存

5.1.4 利用BIOS中断0x15子功能0x88获取内存

5.1.5 实战内存容量检测


5.1 获取物理内存容量

操作系统是计算机硬件的管家,它不仅要知道自己安装了哪些硬件,还得给出有效得当的管理措施,按照预定的一套管理策略使硬件资源得到合理的运用。

5.1.1 学习 Linux 获取内存的方法

通过调用 BIOS 中断 0x15 实现,分别是 BIOS 中断 0x15 的3个子功能,子功能号要存放到寄存器 EAX 或 AX 中。

  • EAX=0xE820:遍历主机上全部内存。
  • AX =0xE801: 分别检测低 15MB 和 16MB~4GB 的内存,最大支持 4GB。
  • AH=0x88:最多检测出 64MB 内存,实际内存超过此容量也按照 64MB 返回。

BIOS 中断是实模式下的方法,只能在进入保护模式前调用。

5.1.2 利用 BIOS中断 0x15 子功能 0xe820 获取内存

BIOS 中断 0x15 的子功能 0xE820 能够获取系统的内存布局,按照类型属性来划分这片系统内存。

5.1.3 利用BIOS中断 0x15 子功能 0xe801 获取内存

5.1.4 利用BIOS中断0x15子功能0x88获取内存

该方法使用最简单,但功能也最简单,简单到只能识别最大 64MB 的内存。即使内存容量大于 64MB,也只会显示 63MB。

5.1.5 实战内存容量检测

   %include "boot.inc"section loader vstart=LOADER_BASE_ADDRLOADER_STACK_TOP equ LOADER_BASE_ADDR;构建gdt及其内部的描述符GDT_BASE:   dd    0x00000000 dd    0x00000000CODE_DESC:  dd    0x0000FFFF dd    DESC_CODE_HIGH4DATA_STACK_DESC:  dd    0x0000FFFFdd    DESC_DATA_HIGH4VIDEO_DESC: dd    0x80000007	       ; limit=(0xbffff-0xb8000)/4k=0x7dd    DESC_VIDEO_HIGH4  ; 此时dpl为0GDT_SIZE   equ   $ - GDT_BASEGDT_LIMIT   equ   GDT_SIZE -	1 times 60 dq 0					 ; 此处预留60个描述符的空位(slot)SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0         ; 相当于(CODE_DESC - GDT_BASE)/8 + TI_GDT + RPL0SELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0	 ; 同上SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0	 ; 同上 ; total_mem_bytes用于保存内存容量,以字节为单位,此位置比较好记。; 当前偏移loader.bin文件头0x200字节,loader.bin的加载地址是0x900,; 故total_mem_bytes内存中的地址是0xb00.将来在内核中咱们会引用此地址total_mem_bytes dd 0					 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;以下是定义gdt的指针,前2字节是gdt界限,后4字节是gdt起始地址gdt_ptr  dw  GDT_LIMIT dd  GDT_BASE;人工对齐:total_mem_bytes4字节+gdt_ptr6字节+ards_buf244字节+ards_nr2,共256字节ards_buf times 244 db 0ards_nr dw 0		      ;用于记录ards结构体数量loader_start:;-------  int 15h eax = 0000E820h ,edx = 534D4150h ('SMAP') 获取内存布局  -------xor ebx, ebx		      ;第一次调用时,ebx值要为0mov edx, 0x534d4150	      ;edx只赋值一次,循环体中不会改变mov di, ards_buf	      ;ards结构缓冲区
.e820_mem_get_loop:	      ;循环获取每个ARDS内存范围描述结构mov eax, 0x0000e820	      ;执行int 0x15后,eax值变为0x534d4150,所以每次执行int前都要更新为子功能号。mov ecx, 20		      ;ARDS地址范围描述符结构大小是20字节int 0x15jc .e820_failed_so_try_e801   ;若cf位为1则有错误发生,尝试0xe801子功能add di, cx		      ;使di增加20字节指向缓冲区中新的ARDS结构位置inc word [ards_nr]	      ;记录ARDS数量cmp ebx, 0		      ;若ebx为0且cf不为1,这说明ards全部返回,当前已是最后一个jnz .e820_mem_get_loop;在所有ards结构中,找出(base_add_low + length_low)的最大值,即内存的容量。mov cx, [ards_nr]	      ;遍历每一个ARDS结构体,循环次数是ARDS的数量mov ebx, ards_buf xor edx, edx		      ;edx为最大的内存容量,在此先清0
.find_max_mem_area:	      ;无须判断type是否为1,最大的内存块一定是可被使用mov eax, [ebx]	      ;base_add_lowadd eax, [ebx+8]	      ;length_lowadd ebx, 20		      ;指向缓冲区中下一个ARDS结构cmp edx, eax		      ;冒泡排序,找出最大,edx寄存器始终是最大的内存容量jge .next_ardsmov edx, eax		      ;edx为总内存大小
.next_ards:loop .find_max_mem_areajmp .mem_get_ok;------  int 15h ax = E801h 获取内存大小,最大支持4G  ------
; 返回后, ax cx 值一样,以KB为单位,bx dx值一样,以64KB为单位
; 在ax和cx寄存器中为低16M,在bx和dx寄存器中为16MB到4G。
.e820_failed_so_try_e801:mov ax,0xe801int 0x15jc .e801_failed_so_try88   ;若当前e801方法失败,就尝试0x88方法;1 先算出低15M的内存,ax和cx中是以KB为单位的内存数量,将其转换为以byte为单位mov cx,0x400	     ;cx和ax值一样,cx用做乘数mul cx shl edx,16and eax,0x0000FFFFor edx,eaxadd edx, 0x100000 ;ax只是15MB,故要加1MBmov esi,edx	     ;先把低15MB的内存容量存入esi寄存器备份;2 再将16MB以上的内存转换为byte为单位,寄存器bx和dx中是以64KB为单位的内存数量xor eax,eaxmov ax,bx		mov ecx, 0x10000	;0x10000十进制为64KBmul ecx		;32位乘法,默认的被乘数是eax,积为64位,高32位存入edx,低32位存入eax.add esi,eax		;由于此方法只能测出4G以内的内存,故32位eax足够了,edx肯定为0,只加eax便可mov edx,esi		;edx为总内存大小jmp .mem_get_ok;-----------------  int 15h ah = 0x88 获取内存大小,只能获取64M之内  ----------
.e801_failed_so_try88: ;int 15后,ax存入的是以kb为单位的内存容量mov  ah, 0x88int  0x15jc .error_hltand eax,0x0000FFFF;16位乘法,被乘数是ax,积为32位.积的高16位在dx中,积的低16位在ax中mov cx, 0x400     ;0x400等于1024,将ax中的内存容量换为以byte为单位mul cxshl edx, 16	     ;把dx移到高16位or edx, eax	     ;把积的低16位组合到edx,为32位的积add edx,0x100000  ;0x88子功能只会返回1MB以上的内存,故实际内存大小要加上1MB.mem_get_ok:mov [total_mem_bytes], edx	 ;将内存换为byte单位后存入total_mem_bytes处。;-----------------   准备进入保护模式   -------------------
;1 打开A20
;2 加载gdt
;3 将cr0的pe位置1;-----------------  打开A20  ----------------in al,0x92or al,0000_0010Bout 0x92,al;-----------------  加载GDT  ----------------lgdt [gdt_ptr];-----------------  cr0第0位置1  ----------------mov eax, cr0or eax, 0x00000001mov cr0, eaxjmp dword SELECTOR_CODE:p_mode_start	     ; 刷新流水线,避免分支预测的影响,这种cpu优化策略,最怕jmp跳转,; 这将导致之前做的预测失效,从而起到了刷新的作用。
.error_hlt:		      ;出错则挂起hlt[bits 32]
p_mode_start:mov ax, SELECTOR_DATAmov ds, axmov es, axmov ss, axmov esp,LOADER_STACK_TOPmov ax, SELECTOR_VIDEOmov gs, axmov byte [gs:160], 'P'jmp $

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/350552.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

html网页右侧悬浮代码,html悬浮窗口代码

怎么才能在HTML中做个悬浮窗并在里面插个超链接。给你上传了附件&#xff0c;里面是源码&#xff0c;你去下载在悬浮框里面加上超链接就行了*{ padding:0px; margin:0px;}.box{ width html弹出悬浮窗口代码,怎么实现啊 &#xff1f;&#xff1f;&#xff1f; 动态生成div设置di…

网站html漂浮代码大全,网页漂浮窗口代码

漂浮窗口代码 var x = 50,y = 60 var xin = true, yin = true var step = 1 var delay = 10 var obj=document.getElementById("ad") function floatAD() {var L=T=0 var R= document.body.clientWidth-obj.offsetWidth var B = document.body.clientHeight-obj.offs…

【商品页面详情页+商品评论】API接口技术交流,封装接口

商品详情API接口数据&#xff1a;提供了商品的基本信息&#xff0c;包括商品名称、描述、规格、价格、销量、库存等信息。此外&#xff0c;也可以通过提供的API接口来获取商品的图片、评价、物流信息等详细数据。 商品评论接口是消费者对商品所进行的客观评价 电商API的应用价…

JS实现漂浮广告功能

JS实现漂浮广告功能 前言一、漂浮广告案例 前言 漂浮广告非常简单也是老案例了&#xff0c;在网页的设计中可直接拿去用&#xff0c;原理都是我之前文章所讲到的&#xff0c;如果有什么不明白的可以看看我之前的文章&#xff0c;仅供参考学习。 一、漂浮广告案例 我在这个案例…

页面漂浮物代码

有时候 会让屏幕中 出现一些漂浮的小图片 eg&#xff1a;这个就是钱袋 漂浮往下掉的 代码&#xff1a; function playFloatBox(content, type) { if (!content) return; var bom type 1 ? <span><i class"fa fa- content "></i></sp…

安卓系统浏览器开发

预置某个浏览器为系统默认的浏览器 描述: 当系统存在多个浏览器时&#xff0c;如何预置某个浏览器为系统默认的浏览器&#xff1f; 方法: 1.在PackageManagerService.java中的构造函数结尾添加&#xff1a;setDefaultBrowser(); 2.setDefaultBrowser()的具体实现&#xff…

Nginx踩坑记录 配置文件中的include不能嵌套 (include的文件里不能再include其他文件了)

上一篇文章介绍了配置文件有多个位置&#xff0c;并且可以采用include实现主配置文件分文件的个性化配置模式&#xff1a;Nginx配置文件 所在路径 到底在哪&#xff1f;_身价五毛的博客-CSDN博客 然后就又踩坑了&#xff0c;include不能嵌套调用&#xff0c;即&#xff1a; …

Vulkan内存模型+管理

前言 最近在研究Vulkan&#xff0c;在Vulkan中使用内存是个麻烦的过程&#xff0c;而且容易用错&#xff0c;今天就给大家分享下Vulkan的内存模型。 内存&#xff0c;在任何时候都是个稀缺的资源&#xff0c;内存管理更是个让人望而却步的事情。在这个崇尚用户体验的今天&…

自学测试半年,终于收到了字节的offer,那一刻我哭出了声...

我是一名毕业于普通一本的化学专业学生&#xff0c;毕业的两年时间里&#xff0c;我一直奔波在化工厂里。每天工作三班倒&#xff0c;下了班就是一包烟一瓶酒&#xff0c;生活过得非常堕落。 原本想着虽然每天很累&#xff0c;但是至少稳定。然而没有想到的是&#xff0c;化工…

注册表启动项设置方法

1、按winr&#xff0c;打开运行输入框&#xff0c;输入regedit&#xff0c;打开注册表。 2、在注册表输入框中复制下面路径&#xff1a; \HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run 3、新增一条开机启动项 右键 -新建-字符串值&#xff0c;修改启动项…

计算机启动项在什么地方找,W7系统注册表开机启动项在哪里

开机启动项除了可以使用MSConfig命令打开以外&#xff0c;也能使用第三方工具、注册表查看开机启动项&#xff0c;因为数值的存在&#xff0c;注册表看到的启动项比较准确。为了个人信息安全&#xff0c;使用注册表编辑开机启动项以更好的杜绝病毒自启动。阅读下文了解w7系统注…

WIN10 注册表添加启动项

1、打开运行&#xff0c;输入“regedit”&#xff0c;打开注册表。 2、在注册表中找到如下位置\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run,右键“Run”新建一个字符串类型的键值。 3、右键新建的键值&#xff0c;选择“修改”&#xff0c;将数值名称…

WINDOW 注册表添加启动项

注册表添加启动项 1、打开运行&#xff0c;输入“regedit”&#xff0c;打开注册表。 2、在注册表中找到如下位置HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run&#xff0c;winwin7.com右键“Run”新建一个字符串类型的键值。 3、右键新建的键值&…

修改注册表开机启动项

首先我们启动项的位置&#xff0c;它有两个一个是user一个是michine我们先来看HKEY_CURRENT_USER下面的&#xff0c;打开注册表方式非常简单笔记本winR台式机可以直接点击开始运行输入regedit 找到注册表之后依次展开HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVe…

win10添加开机启动项_Windows系统注册表添加开机启动项

Windows 7系统我们可以把需要开机启动的软件把快捷键放到(开始/程序/启动)就可以了&#xff0c;而Windows 10系统没有(开始/程序/启动)启动项&#xff0c;我们要添加软件开机自动启动就需要到注册表添加修改&#xff0c;而注册表里面添加启动项有两个类型&#xff0c; 1、[HKEY…

屏蔽360阻止远程执行变更注册表自启动数据的办法

屏蔽360阻止远程执行变更注册表自启动数据的办法 运程服务器上的程序&#xff0c;由于需要。我在服务器中&#xff0c;加入更新升级自身&#xff08;exe&#xff09;文件&#xff0c;并变更操作系统自启动数据的代码。 实践证明&#xff0c;通过客户端&#xff0c;调用运程服务…

实验一——病毒注册表操作

【实验内容】 &#xff08;1&#xff09;强制隐藏.exe文件的扩展名 刚开始应用程序的exe扩展名都是可见的 1、注册表项&#xff1a;HKEY_CLASS_ROOT\exefile&#xff0c; 2、新建字符串值&#xff1a;取名为NeverShowExt。 用Mytool工具&#xff1a; 直接在注册表中添加 …

win7系统注册表开机启动项如何打开?

在运行窗口输入MSConfig命令不仅可以打开开机启动项&#xff0c;也能使用第三方工具、注册表查看开机启动项&#xff0c;注册表看到的启动项比较准确。而且使用注册表编辑开机启动项以更好的杜绝病毒自启动。一些win7的用户反馈说不知道win7系统注册表开机启动项如何打开&#…

揭秘广告投放的9大关键环节,了解真相让你成为广告投放高手!

正式开始本章的内容之前&#xff0c;先来简单复习一下上一章的主要内容&#xff1a; 核心要点1&#xff1a;广告投放的意义主要有三点&#xff1a;传播品牌、宣传产品、促成转化&#xff1b; 核心要点2&#xff1a;广告投放的主要流程有这样 9 个阶段&#xff1a; 本章我们以…

(栈和队列) 1047. 删除字符串中的所有相邻重复项 ——【Leetcode每日一题】

❓1047. 删除字符串中的所有相邻重复项 难度&#xff1a;简单 给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回…