当前位置: 首页 > wzjs >正文

想做网站建设seo网络排名优化

想做网站建设,seo网络排名优化,淮安品牌网站建设,股票网站建设文章目录 前言获取物理内存容量利用 BIOS 中断 0x15 子功能 0xe820 获取内存利用 BIOS 中断 0x15 子功能 0xe801 获取内存利用 BIOS 中断 0x15 子功能 0x88 获取内存内存容量检测代码编译运行 结语 前言 经过上一章的学习实践,目前我们已经进入32位保护模式了。本章…

文章目录

    • 前言
    • 获取物理内存容量
      • 利用 BIOS 中断 0x15 子功能 0xe820 获取内存
      • 利用 BIOS 中断 0x15 子功能 0xe801 获取内存
      • 利用 BIOS 中断 0x15 子功能 0x88 获取内存
      • 内存容量检测代码
      • 编译运行
    • 结语

前言

经过上一章的学习实践,目前我们已经进入32位保护模式了。本章的标题是保护模式进阶,向内核迈进,那么就是要在保护模式下进一步编程。

郑钢老师在上一章提到,之前的四章偏向于理论,代码量相对较小,接下来的章节代码量会更多,这对我而言会是一个挑战。

这章内容较多,我打算花2-3天时间完成学习,博客也会分成若干部分,每部分完成一节内容。

第四章知识笔记博客链接:《操作系统真象还原》第四章(1)-CSDN博客

第四章实践部分博客链接:《操作系统真象还原》第四章(2)-CSDN博客

本章参考博客链接:《操作系统真象还原》第五章 ---- 轻取物理内存容量 启用分页畅游虚拟空间 力斧直斩内核先劈一角 闲庭信步摸谈特权级_真象还原 分页 info tab-CSDN博客


获取物理内存容量

保护模式可以访问4GB内存,为了维护这么大的内存空间,就要有相应的内存管理体系。想要管理内存,首先就要先获取内存容量,bios可以通过0x15中断获取内存信息,bios是在实模式下运行的,我们要在进入保护模式之前获取内存容量。

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

子功能 0xE820 的强大之处是返回的内存信息较丰富,包括多个属性字段,所以需要一种格式结构来组织这些数据。内存信息的内容是用地址范围描述符来描述的,用于存储这种描述符的结构称之为地址范围描述符(Address Range Descriptor Structure,ARDS)。

ards长20字节,分为5段,每段4字节,每次调用0x15就会返回一个这样结构的数据。

字节偏移量属性名称描述
0BaseAddrLow第32位基地址
4BaseAddrHigh高32位基地址
8LengthLow低32位内存长度,以字节为单位
12LengthHigh高32位内存长度,以字节为单位
16Type本段内存类型

关于type字段

Type 值名 称描 述
1AddressRangeMemory这段内存可以被操作系统使用
2AddressRangeReserved内存使用中或者被系统保留,操作系统不可以用此内存
其他未定义未定义,将来会用到,目前保留。但是需要操作系统一样将其视为ARR(AddressRangeReserved)

关于0x15中断的0xe820子功能的参数

调用或返回寄存器或状态位参 数 用 途
输入EAX子功能号:EAX 寄存器用来指定子功能号,此处输入为 0xE820
EBXARDS 后续值:内存信息需要按类型分多次返回,由于每次执行一次中断都只返回一种类型内存的 ARDS 结构,所以要记录下一个待返回的内存 ARDS,在下一次中断调用时通过此值告诉 BIOS 该返回哪个 ARDS,这就是后续值的作用。第一次调用时一定要置为 0,EBX具体值我们不用关注,字取决于具体 BIOS 的实现。每次中断返回后,BIOS 会更新此值
ES:DIARDS 缓冲区:BIOS 将获取到的内存信息写入此寄存器指向的内存,每次都以 ARDS 格式返回
ECXARDS 结构的字节大小:用来指示 BIOS 写入的字节数。调用者和 BIOS 都同时支持的大小是 20 字节,将来也许会扩展此结构
EDX固定为签名标记 0x534d4150,此十六进制数字是字符串 SMAP 的 ASCII 码:BIOS 将调用者正在请求的内存信息写入 ES:DI 寄存器所指向的 ARDS 缓冲区后,再用此签名校验其中的信息
输出CF 位若 CF 位为 0 表示调用未出错,CF 为 1,表示调用出错
EAX字符串 SMAP 的 ASCII 码 0x534d4150
ES:DIARDS 缓冲区地址,同输入值是一样的,返回时此结构中已经被BIOS 填充了内存信息
ECXBIOS 写入到 ES:DI 所指向的 ARDS 结构中的字节数,BIOS 最小写入 20 字节
EBX后续值:下一个 ARDS 的位置。每次中断返回后,BIOS 会更新此值,BIOS 通过此值可以找到下一个待返回的 ARDS 结构,咱们不需要改变 EBX 的值,下一次中断调用时还会用到它。在 CF 位为 0 的情况下,若返回后的 EBX 值为 0,表示这是最后一个 ARDS 结构

此中断的调用步骤如下。

  1. 填写好“调用前输入”中列出的寄存器。
  2. 执行中断调用 int 0x15。
  3. 在 CF 位为 0 的情况下,“返回后输出”中对应的寄存器便会有对应的结果。

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

这种方法相对简单,但是只能识别4GB内存,而且数据放到两个寄存器里。低于 15MB 的内存以 1KB 为单位大小来记录,单位数量在寄存器 AX 和 CX 中记录,其中 AX 和 CX 的值是一样的,所以在 15MB 空间以下的实际内存容量=AX*1024。AX、CX 最大值为 0x3c00,即 0x3c00*1024=15MB。16MB~4GB 是以 64KB 为单位大小来记录的,单位数量在寄存器 BX 和 DX 中记录,其中 BX 和 DX 的值是一样的,所以 16MB 以上空间的内存实际大小=BX*64*1024

为什么要分成两部分,分界线是16mb?为了兼容有24根地址总线的80286cpu,此cpu寻址范围是16mb,当时有一些isa设备要利用15-16mb空间作为缓冲区,出现了内存空洞。后续cpu为了兼容286保留了这一特性。

相关参数如下

调用或返回寄存器或状态位描述
输入AX子功能号:0xE801
输出CF若 CF 位为 0 表示调用未出错,CF 为 1,表示调用出错
AX以 1KB 为单位,只显示 15MB 以下的内存容量,故最大值为 0x3c00,即AX 表示的最大内存为 0x3c00*1024=15MB
BX以 64KB 为单位,内存空间 16MB~4GB 中连续的单位数量,即内存大小为 BX*64x1024 字节
CX同AX
DX同BX

此中断的调用步骤如下。

  1. 将 AX 寄存器写入 0xE801。
  2. 执行中断调用 int 0x15。
  3. 在 CF 位为 0 的情况下,“返回后输出”中对应的寄存器便会有对应的结果。

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

最后一个获取内存的方法也同样是 BIOS 0x15 中断,子功能号是 0x88。该方法使用最简单,只能识别最大 64MB 的内存。使用的时候结构要加上1MB。

输入:AH 子功能号:0x88

输出:1.CF 位 若 CF 位为 0 表示调用未出错,CF 为 1,表示调用出错

2.AX 以 1KB 为单位大小,内存空间 1MB 之上的连续单位数量,不包括低端1MB 内存。故内存大小为 AX*1024 字节+1MB

此中断的调用步骤如下。

(1)将 AX 寄存器写入 0x88。

(2)执行中断调用 int 0x15。

(3)在 CF 位为 0 的情况下,“返回后输出”中对应的寄存器便会有对应的结果。

内存容量检测代码

关于jxx组指令的参考博客:汇编跳转指令: JMP、JECXZ、JA、JB、JG、JL、JE、JZ、JS、JC、JO、JP 等_jg指令-CSDN博客

%include "boot.inc"
section loader vstart=LOADER_BASE_ADDRLOADER_STACK_TOP equ LOADER_BASE_ADDRjmp loader_start
;-------------------- 这部分完成GDT和4个段描述符的构建 --------------------------------
;编译后程序的地址是越来越高的,所以代码要先开辟低地址再开辟高地址。8字节64位是一个段描述符。dd命令开辟出一个4字节32位空间。
GDT_BASE:dd 0x00000000dd 0x00000000		;第一个段描述符无法使用,开辟出来空着
CODE_DESC:dd 0x0000ffff		;前四位是16位段基址,设置为0,后四位是16位段界限,设置为1。高位在前低位在后dd DESC_CODE_HIGH4	;提前在配置文件中写好的高32位
DATA_STACK_DESC:dd 0x0000ffffdd DESC_DATA_HIGH4	;数据和栈用相同的段描述符,具体说明看博客
VIDEO_DESC:dd 0x80000007		;这部分请看博客里的说明。dd DESC_VIDEO_HIGH4
;-------------------- 这部分完成GDT大小的计算,同时预留出60个段描述符的空间 --------------------------------
;这部分为加载gdt做准备。dq定义4字8字节64位。times是nasm提供的伪指令,作用是循环。以后我们还要向gdt里添加别的表符,这里提前留出位置。GDT_SIZE equ $-GDT_BASEGDT_LIMIT equ GDT_SIZE-1times 59 dq 0times 5 db 0
;-------------------- 这部分完成构建选择子 --------------------------------
;选择子放在段寄存器里,16位大小,高13位是gdt的索引,第2位是ti位,指示索引是gdt的还是ldt的,0、1两位是特权级位。SELECTOR_CODE equ (0x0001<<3)+TI_GDT+RPL0	;0001就是下标1,左移3位相当于*8,因为一个表项是8字节SELECTOR_DATA equ (0x0002<<3)+TI_GDT+RPL0SELECTOR_VIDEO equ (0x0003<<3)+TI_GDT+RPL0
;-------------------- 这部分设置保存内存容量的标号--------------------------------
;关于这个标号的地址,loader.S的起始地址是0x900,这行前面有64个8字节的段描述符,所以这里是0x900+0x200=0xb00total_mem_bytes dd 0	;初始为0,最终变成总内存容量
;-------------------- 这部分完成定义GDT指针 --------------------------------
gdt_ptr:dw GDT_LIMIT	;前2字节是gdt的界限dd GDT_BASE		;后4字节是gdt的起始位置
;-------------------- 这部分实现三种获取内存容量的方法 --------------------------------
;注意我们这次删除了实模式下打印字符串的功能ards_buf times 244 db 0	;设置ards缓冲区,存放ardsards_nr dw 0		;用于记录ards结构体的数量;这两行开辟256字节的空间,人工对齐loader_start:
;-------------------- 方法1:利用0xe820获取内存 --------------------------------
;以下部分,通过0xe801获取所有的ardsxor ebx,ebx		;用异或置零,初始ebx设置为0,后续我们不需要再处理mov edx,0x534d4150	;固定值mov di,ards_buf		;es:di指向缓冲区,es在mbr设置,这里修改di即可
.e820_mem_get_loop:mov eax,0x0000e820	;因为执行完int 0x15后eax,ebx,ecx会变化,所以每次循环都要重新设置mov ecx,20		;返回的字节数,固定为20int 0x15jc .e820_failed_so_try_e801 ;如果e820失败,尝试e801add di,cx		;+20字节指向下一个ardsinc word [ards_nr]	;记录ards数量cmp ebx,0		;如果ebx=0且cf=0,所有ards全部返回jnz .e820_mem_get_loop 	;如果ebx!=0,继续循环
;以下部分,遍历ards,找到最大的32位基地址+内存长度,即为最大内存容量mov cx,[ards_nr]mov ebx,ards_bufxor edx,edx		;edx保存最大内存容量,初始置0
.find_max_mem_area:mov eax,[ebx]		;32位基地址add eax,[ebx+8]		;内存长度add ebx,20		;指向下一个ardscmp edx,eaxjge .next_ards		;如果edx>=eax,跳转到下一个ards,否则让edx=eax,最终效果是找到最大的ardsmov edx,eax
.next_ards:loop .find_max_mem_areajmp .mem_get_ok
;-------------------- 方法2:利用0xe801获取内存 --------------------------------
;返回后,ax=cx单位是1kb,里面是小于16mb的单位数,bx=dx单位是64kb,里面是大于16mb的单位数。最终需要转化为字节数。
.e820_failed_so_try_e801:mov ax,0x0000e801int 0x15jc .e801_failed_so_try88	;如果e801失败,尝试88方法
;以下计算出低于16mb的内存容量大小mov cx,0x400		;1024mul cx			;16位乘法,结果是32位,低16在ax,高16在dxshl edx,16		;左移16位and eax,0x0000ffff	;保留低16位or edx,eax		;拼接edx的高16位和eax低16位,放到edx中add edx,0x100000	;+1mb,原因是获取的内存比实际内存少1mbmov esi,edx		;备份edx
;以下计算16mb以上内存容量大小xor eax,eaxmov ax,bx		;大于16mb的单位数存在bx、dx里mov ecx,0x10000		;单位是64kbmul ecx			;32位乘法,结果是64位,低32位在eax,高32位在edxadd esi,eax		;这种方法的上限就是4gb,所以不必理会高32位,只需要把低32位加进结果即可mov edx,esijmp .mem_get_ok
;-------------------- 方法3:利用0x88获取内存 --------------------------------
;这部分是方法2的简化版,代码参考2,不再写注释
.e801_failed_so_try88:mov ah,0x88int 0x15jc .error_hltand eax,0x0000ffffmov cx,0x400mul cxshl edx,16or edx,eaxadd edx,0x100000
;-------------------- 这部分记录内存容量 --------------------------------
;如果三种方法都失败,跳转到这里,进行一个死循环
.error_hlt:jmp $
;不管使用了哪种子命令,只要成功,都要跳转到这里记录,单位是1字节
.mem_get_ok:mov [total_mem_bytes],edx	;在total_mem_bytes地址记录总内存容量
;-------------------- 这部分完成进入保护模式的三个步骤 --------------------------------in al,0x92 or al,0000_0010B out 0x92,al 		;打开 A20lgdt [gdt_ptr] 		;加载 GDTmov eax, cr0 or eax, 0x00000001 mov cr0, eax		;cr0 第 0 位置 1
;-------------------- 验证是否进入保护模式 --------------------------------jmp dword SELECTOR_CODE:p_mode_start ; 刷新流水线
[bits 32] 
p_mode_start: mov ax,SELECTOR_DATA mov ds,ax mov es,ax mov ss,ax mov esp,LOADER_STACK_TOP mov ax,SELECTOR_VIDEOmov gs,ax mov byte [gs:160], 'P' ;通过显卡打印一个字符,验证是否进入保护模式jmp $

编译运行

这里我顺手调整了一下mbr,所以先编译写入mbr

nasm -I include/ -o mbr.bin mbr.S
dd if=/home/hongbai/bochs/mbr.bin of=/home/hongbai/bochs/bin/c.img bs=512 count=1 conv=notrunc

编译写入loader

nasm -I include/ -o loader.bin loader.S
dd if=/home/hongbai/bochs/loader.bin of=/home/hongbai/bochs/bin/c.img bs=512 count=4 seek=2 conv=notrunc

运行bochs

cd bin
./bochs -f bochsrc.disk

结果截图:

我们先打开bochsrc.disk配置文件,看一下我们给bochs配置了多少内存。内存大小是megs行,我设置的是512mb大小。

在控制台输入ctrl+c,中断bochs运行,再输入xp 0xb00,查看内存容量是否探测成功。结果如下:

0x20000000正是我设置的512MB内存大小,说明程序运行正常。


结语

这一部分没什么好说的,主要就是完成获取内存容量的功能,新增了一些代码。后续还有内存分页,加载内核,特权级几部分内容,我计划在清明假期把它们全部完成,最后写一个大总结。

http://www.dtcms.com/wzjs/249498.html

相关文章:

  • 需要做网站设计的公司竞价运营是做什么的
  • 网站空间独立控制面板宁波网站关键词优化代码
  • 阿里云做网站教程在线培训平台有哪些
  • 公司网站有哪些重要性品牌传播策划方案
  • 网站建设加盟哪个好小红书推广运营
  • 东莞做企业网站海外短视频软件
  • 中山企业网站建设方案汕头百度网络推广
  • 网站空间如何使用排名seo公司哪家好
  • 做电脑网站与手机上的一样吗百度自然排名优化
  • 山西网站推广公司网页制作免费网站制作
  • 装潢网站模板seo培训教程视频
  • 南京市秦淮区建设局网站网络推广大概需要多少钱
  • 5款免费网站管理系统杭州seo搜索引擎优化
  • wordpress配置网页出现404错误seo网络优化平台
  • 上海网站制作公司多少钱在线seo关键词排名优化
  • 公司网站首页导航html优化大师电脑版下载
  • ps外包网站国际足联世界排名
  • 一个软件开发团队需要哪些人北京seo专员
  • 临沂做网站优化百度网址大全下载
  • 哈尔滨企业建站服务商济南seo排名优化推广
  • 建设网站q8555 3807360优化大师下载
  • 建设电影网站如何赚钱seo网站排名查询
  • 牡丹江3d网站开发汕头seo全网营销
  • 营销式网站建设站长之家下载
  • 怎么做高端品牌网站设计外国黄冈网站推广平台
  • 怎样在别人网站做加强链接百度经验手机版
  • 郑州做网站要学计算机哪个培训机构好
  • 网站建设补贴高端网站定制设计
  • 水利部建设管理与安全中心网站谷歌独立站推广
  • 品牌网站制作公司哪家好发布悬赏任务的推广平台