操作系统真相还原_第5章第1节:利用BIOS中断0x15 获取内存信息

news2024/11/15 19:43:03

文章目录

    • 功能号
    • 返回信息
    • 功能号详解
      • 子功能号:0xE820
      • 子功能号:0xE801
      • 子功能号:0x88
    • 内存检测示例
      • 当前内存分布
      • 说明
      • 程序
        • boot.inc
        • mbr.s
        • loader.s
      • 编译并写入硬盘
      • 启动bochs运行

功能号

EAX=0xE820:遍历主机上全部内存
AX=0xE801:分别检测低15MB和16~4GB的内存
AH=0x88:最多检测64MB,超过64MB也按照64MB返回

返回信息

返回信息是用地址范围描述符来描述的,用于存储这种描述符的结构称之为地址范围描述符(Address Range Descriptor Structure, ARDS)
此数据结构共有5个字段,每个字段大小都是4byte,如下
BaseAddrLow,0~3字节:基地址的低32位
BaseAddrHigh,4~7字节:基地址的高32位
LengthLow,8~11字节:内存长度的低32位,以byte为单位
LengthHigh,12~15字节:内存长度的高32位,以byte为单位
Type,16~19字节:本段内存的类型

Type字段解释:
type值=1,AddressRangeMemory,表示可被操作系统使用
type值=2,AddressRangeReserved,表示被系统保留,操作系统不可用
type值=其他值,未定义,将来会用到,被操作系统视为AddresssRangeReserved

功能号详解

子功能号:0xE820


子功能号:0xE801


示例:

子功能号:0x88

内存检测示例

当前内存分布

说明

boot.inc包含loader加载所需的参数,以及打开保护模式所需的全局描述符
mbr.s程序:在窗口中输出"enter mbr",然后加载loader.s程序到0x7E00
loader.s程序:在窗口中输出"enter loader",然后使用BIOS中断0x15的子功能0xE820获取可用内存信息并输出在窗口中,最后进入保护模式在窗口中输出"enter protect mode"

程序

boot.inc

;--------- mbr & loader ---------
LBA_START_SECTOR equ 0x1
SECTOR_COUNT equ 0x4
LOADER_BASE_ADDR equ 0x7E0
LOADER_OFF_ADDR equ 0x0
LOADER_ADDR equ 0x7E00
ARDS_ADDR equ 0x1000

;--------- gdt ---------
DESC_G_4K   equ	  1_00000000000000000000000b   
DESC_D_32   equ	   1_0000000000000000000000b
DESC_L	    equ	    0_000000000000000000000b
DESC_AVL    equ	     0_00000000000000000000b
DESC_LIMIT_CODE2  equ 1111_0000000000000000b
DESC_LIMIT_DATA2  equ DESC_LIMIT_CODE2
DESC_LIMIT_VIDEO2  equ 0000_000000000000000b
DESC_P	    equ		  1_000000000000000b
DESC_DPL_0  equ		   00_0000000000000b
DESC_DPL_1  equ		   01_0000000000000b
DESC_DPL_2  equ		   10_0000000000000b
DESC_DPL_3  equ		   11_0000000000000b
DESC_S_CODE equ		     1_000000000000b
DESC_S_DATA equ	  DESC_S_CODE
DESC_S_sys  equ		     0_000000000000b
DESC_TYPE_CODE  equ	      1000_00000000b	;x=1,c=0,r=0,a=0 代码段是可执行的,非依从的,不可读的,已访问位a清0.  
DESC_TYPE_DATA  equ	      0010_00000000b	;x=0,e=0,w=1,a=0 数据段是不可执行的,向上扩展的,可写的,已访问位a清0.

;code section
DESC_CODE_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_CODE2 + DESC_P + DESC_DPL_0 + DESC_S_CODE + DESC_TYPE_CODE + 0x00

;data section
DESC_DATA_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_DATA2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x00

;video section
DESC_VIDEO_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_VIDEO2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x0b

;--------------   选择子属性  ---------------
RPL0  equ   00b
RPL1  equ   01b
RPL2  equ   10b
RPL3  equ   11b
TI_GDT	 equ   000b
TI_LDT	 equ   100b

mbr.s

;主引导程序
;------------------------------------------------------------
%include "boot.inc"
SECTION MBR vstart=0x7c00         
   mov ax,cs      
   mov ds,ax
   mov es,ax
   mov ss,ax
   mov fs,ax
   mov ax, 0xB800
   mov gs, ax
   mov sp,0x7c00

; 清屏 利用0x06号功能,上卷全部行,则可清屏。
; -----------------------------------------------------------
;INT 0x10   功能号:0x06	   功能描述:上卷窗口
;------------------------------------------------------
;输入:
;AH 功能号= 0x06
;AL = 上卷的行数(如果为0,表示全部)
;BH = 上卷行属性
;(CL,CH) = 窗口左上角的(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;无返回值:
   mov     ax, 0x600
   mov     bx, 0x700
   mov     cx, 0           ; 左上角: (0, 0)
   mov     dx, 0x184f	   ; 右下角: (80,25),
			   ; VGA文本模式中,一行只能容纳80个字符,共25行。
			   ; 下标从0开始,所以0x18=24,0x4f=79
   int     0x10            ; int 0x10


;;;;;;;;;     打印字符串    ;;;;;;;;;;;

   mov cx, sx - msg
   mov si, msg
   mov di, 0
show_str:
   mov byte al, [si]
   mov byte ah, [sx]
   mov word [gs:di], ax
   inc si
   add di, 2
   loop show_str
   jmp L0

   msg db "enter mbr"
   sx db 0x24

;;;;;;;;;      打字字符串结束	 ;;;;;;;;;;;;;;;
L0:
   push ds
   push di
   mov eax, LBA_START_SECTOR
   push eax
   mov ax, SECTOR_COUNT
   push ax
   mov ax, LOADER_BASE_ADDR
   push ax
   mov ax, LOADER_OFF_ADDR
   push ax
   call read_disk
   add sp, 10
   pop di
   pop ds

   jmp LOADER_ADDR

;;;;;;;;;      read disk      ;;;;;;;;;

; LBA: [bp+10]
; sector count: [bp+8]
; destination: sec=[bp+6], off=[bp+4]
read_disk:
   push bp
   mov bp, sp

;sector_count
   mov dx,0x1f2
   mov ax, [bp+8]
   out dx, al

;sector_addr
   mov dx, 0x1f3
   mov ax, [bp+10]
   out dx, al

   mov dx, 0x1f4
   mov al, ah
   out dx, al

   mov dx, 0x1f5
   mov ax, [bp+12]
   out dx, al

   mov dx, 0x1f6
   mov al, ah
   and al, 0x0f
   or al, 0xe0
   out dx, al

;command_write
   mov dx, 0x1f7
   mov al, 0x20
   out dx, al

disk_test:
   nop          ;give disk a moment
   in al, dx
   and al, 0x88 ;7: BUSY, 3: READY
   cmp al, 0x08 ; (BUSY=0 & READY=1) or not?
   jnz disk_test

;data_read:   
   mov ax, [bp+8]
   mov dx, 256
   mul dx
   mov cx, ax

   mov bx, [bp+4]
   mov ax, [bp+6]
   mov ds, ax

   mov dx, 0x1f0
go_on_read:
   in ax, dx
   mov [bx], ax
   add bx,2
   loop go_on_read

   mov sp, bp
   pop bp
   ret
;;;;;;;;;      read disk      ;;;;;;;;;

   times 510-($-$$) db 0
   db 0x55,0xaa

loader.s

%include "boot.inc"
section loader vstart=LOADER_ADDR
;;;;;;;;;     打印字符串    ;;;;;;;;;;;

   mov cx, sx-msg1
   mov si, msg1
   mov di, 160
show_str:
   mov byte al, [si]
   mov byte ah, [sx]
   mov word [gs:di], ax
   inc si
   add di, 2
   loop show_str

   jmp get_memoinfo

   msg1 db "enter loader"
   sx db 0x24

;;;;;;;;;      打字字符串结束    ;;;;;;;;;;;;;;;

;----- get memory information -----
get_memoinfo:
;----- get all: 0xE820
jmp_e820:
   xor ebx, ebx
   mov edx, 0x534d4150
   mov di, ARDS_ADDR+2
ards_e820:
   mov eax, 0x0000e820
   mov ecx, 20
   int 0x15
   jc Error
   add di, cx
   inc word [ARDS_ADDR]
   cmp ebx, 0
   jnz ards_e820

show_memoinfo:
   mov ax, 0xb800
   mov gs, ax
   mov cx, [ARDS_ADDR]
   mov si, ARDS_ADDR+0x2
   mov di, 320
loop_print:

   push di
addr_info:
   mov edx, [si]
   mov di, memo_addr+22
   call BtH
   shr edx, 16
   mov di, memo_addr+18
   call BtH
   mov edx, [si+4]
   mov di, memo_addr+14
   call BtH
   shr edx, 16
   mov di, memo_addr+10
   call BtH
   
size_info:
   mov edx, [si+8]
   mov di, memo_size+22
   call BtH
   shr edx, 16
   mov di, memo_size+18
   call BtH
   mov edx, [si+12]
   mov di, memo_size+14
   call BtH
   shr edx, 16
   mov di, memo_size+10
   call BtH

type_info:
   mov edx, [si+16]
   mov di, memo_type+14
   call BtH
   shr edx, 16
   mov di, memo_type+10
   call BtH

   pop di
   push cx
   push si
   push di

   mov cx, BtH_Table-memo_addr
   mov ah, 0x24
   mov si, memo_addr
info_print:
   mov al, [si]
   mov [gs:di], ax
   inc si
   add di, 0x2
   loop info_print

   pop di
   add di, 160
   pop si
   add si, 20
   pop cx
   dec cx
   cmp cx, 0
   jne loop_print
   jmp Jmp_there

memo_addr db "ADDR:0xxxxxxxxxxxxxxxxx. "
memo_size db "SIZE:0xxxxxxxxxxxxxxxxx. "
memo_type db "TYPE:0xxxxxxxxx."
BtH_Table db "0123456789ABCDEF"

;params: dx, di
BtH:
   push ax
   push bx
   push edx
   push di
   
   mov bh, 0

   mov bl, dl
   and bl, 00001111b
   mov al, [BtH_Table+bx]
   mov [di], al
   dec di

   mov bl, dl
   shr bl, 4
   mov al, [BtH_Table+bx]
   mov [di], al
   dec di

   mov bl, dh
   and bl, 00001111b
   mov al, [BtH_Table+bx]
   mov [di], al
   dec di

   mov bl, dh
   shr bl, 4
   mov al, [BtH_Table+bx]
   mov [di], al

   pop di
   pop edx
   pop bx
   pop ax
   ret
   
Error:
   
;----- open A20 -----
Jmp_there:
   in al, 0x92
   or al, 00000010b
   out 0x92, al

;----- load gdtr-----
   lgdt [gdt_ptr]

;----- cr0 set -----
   mov eax, cr0
   or eax, 0x00000001
   mov cr0, eax

;----- clear instruction pipeline -----
   jmp dword SELECTOR_CODE:p_m_start

[bits 32]
p_m_start:
   mov ax, SELECTOR_DATA
   mov ds, ax
   mov es, ax
   mov ss, ax
   mov esp, LOADER_ADDR

   mov ax, SELECTOR_VIDEO
   mov gs, ax
   mov ecx, GDT_BASE-msg2
   mov si, msg2
   mov di, 1280
show_str2:
   mov byte al, [si]
   mov byte [gs:di], al
   inc si
   add di, 2
   loop show_str2

   jmp $

;string
msg2 db "enter protect mode"

;GDT_CREATE
GDT_BASE:
   dd 0x00000000, 0x00000000

CODE_DESC:
   dd 0x0000FFFF, DESC_CODE_HIGH4

DATA_DESC:
   dd 0x0000FFFF, DESC_DATA_HIGH4

VIDEO_DESC:
   dd 0x80000007, DESC_VIDEO_HIGH4

GDT_SIZE equ $ - GDT_BASE
GDT_LIMIT equ GDT_SIZE - 1
times 30 dq 0

;SELECTOR_SET
SELECTOR_CODE equ 0000000000001_000b + TI_GDT + RPL0
SELECTOR_DATA equ 0000000000010_000b + TI_GDT + RPL0
SELECTOR_VIDEO equ 0000000000011_000b + TI_GDT + RPL0

;GDT_pointer
gdt_ptr dw GDT_LIMIT
        dd GDT_BASE

编译并写入硬盘

nasm -I OS/include/ -o OS/boot/mbr.bin OS/boot/mbr.s
nasm -I OS/include/ -o OS/boot/loader.bin OS/boot/loader.s
dd if=OS/boot/mbr.bin of=bochs/hd60M.img bs=512 count=1 seek=0 conv=notrunc
dd if=OS/boot/loader.bin of=bochs/hd60M.img bs=512 count=4 seek=1 conv=notrunc

启动bochs运行

./bochs/bin/bochs -f bochs/boot.disk

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

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

相关文章

分享121个ASP源码,总有一款适合您

ASP源码 分享121个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 121个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1wwsIoZidHihm5WHPKjlvMg?pwdew3b 提取码&#x…

如何在linux服务器部署sonar服务?

文章目录前言一、上传sonar插件二、设置sonar插件的权限三、启动插件四、配置环境变量前言 sonar服务是代码质量扫描的工具,我们如何利用sonar进行代码质量扫描还有在linux服务器上部署呢?下面这篇文章详细的记录了我在sonar的使用过程中所遇到的各种坑。 一、上传sonar插件…

十大经典排序算法【算法思想+图解+代码】【数据结构与算法笔记】

前言&#xff1a;文中大部分为本人收集整理&#xff0c;综合学习资料&#xff0c;个人理解……。希望能帮助你少掉写头发&#xff0c;早日走出理解的深渊。因为写作较为仓促文中内容难免会有纰漏&#xff0c;发现可评论区回复&#xff08;无奖&#xff09;。排序(Sort)分析排序…

StudioOne6旗舰版DAW2023跨版本升级新功能介绍

PreSonus2023发布了Studio One 6旗舰级DAW的跨版本升级。他们获奖的DAW软件的这一最新版本引入了大量的新功能和增强功能&#xff0c;包括用户界面的定制选项&#xff0c;PreSonus说这使第6版成为他们迄今为止最个性化的升级。PreSonus发布了旗舰级DAW的跨版本升级&#xff0c;…

Leetcode:131. 分割回文串(C++)

目录 问题描述&#xff1a; 实现代码与解析&#xff1a; 回溯&#xff1a; 原理思路&#xff1a; 问题描述&#xff1a; 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都…

客快物流大数据项目(一百零六):实时ETL处理

文章目录 实时ETL处理 一、业务流程 二、​​

Kettle简介

一、Kettle基本介绍 Kettle(现更名为Pentaho Data Integration-Pentaho)是一款国外开源的ETL工具&#xff0c;纯java编写&#xff0c;可以在Window、Linux、Unix上运行&#xff0c;绿色无需安装。它允许你管理来自不同数据库的数据&#xff0c;通过提供一个图形化的用户环境来…

盒模型应用 改变宽高范围 改变背景覆盖范围 溢出处理 断词规则 空白处理

目录盒模型应用改变宽高范围改变背景覆盖范围溢出处理断词规则 word-break空白处理 溢出的空白处理盒模型应用 改变宽高范围 默认情况下&#xff0c;width 和 height 设置的是内容盒宽高。 页面重构师&#xff1a;将psd文件&#xff08;设计稿&#xff09;制作为静态页面 衡量…

【竞赛题】6297. 根据第 K 场考试的分数排序

题目 班里有 m 位学生&#xff0c;共计划组织 n 场考试。给你一个下标从 0 开始、大小为 m x n 的整数矩阵 score &#xff0c;其中每一行对应一位学生&#xff0c;而 score[i][j] 表示第 i 位学生在第 j 场考试取得的分数。矩阵 score 包含的整数 互不相同 。 另给你一个整数…

【机器学习】多标签分类

目录&#xff1a;多标签分类一、算法1.1 One-vs-Rest1.2 AdaBoost-MH1.3 ML-KNN一、算法 多标签分类的适用场景较为常见&#xff0c;比如&#xff0c;一份歌单可能既属于标签旅行也属于标签驾车。有别于多分类分类&#xff0c;多标签分类中每个标签不是互斥的。多标签分类算法…

Python使用K-means聚类分析

Python使用K-means聚类分析 文章目录Python使用K-means聚类分析介绍1.集群标签作为特征一、k-均值聚类二、示例 - 加州住房2.KMeans总结介绍 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 本文将使用所谓的无监督学习算法。 无监督算法不使用目标&#xff…

软件测试复习11:自动化测试

专栏&#xff1a;《软件测试》 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录自动化测试的前提自动化测试的过程自动化测试的5个级别自动化测试的局限自动化测试的前提 自动化测试可以很好地代替人&#xf…

Facebook运营策略中的SEO优化:10个提示

在过去的一年中&#xff0c; Facebook上的品牌营销预算激增&#xff0c;这就是为什么许多人正在使用 Facebook来推广其业务。然而&#xff0c;并非所有新品牌都可以通过在社交媒体上进行成功的 SEO优化而获得成功。如果你想在 Facebook上销售你的产品或服务&#xff0c;你需要从…

2022年终总结——从打工到创业的转折

目录一、机会的创造和紧抓二、时间线的诉说1.1-4月份&#xff0c;在外面工作的过程中也在考虑这个事情&#xff1b;是在一个自己刚熟悉的金融行业学习提升&#xff1f;还是回归到自己铺垫了很久的教育行业深耕&#xff1f;2.5月份&#xff0c;孤身一人奔赴创业之路&#xff1b;…

《深入浅出计算机组成原理》学习笔记 Day7

电路基础1. 使用电信号的优势2. 继电器3. “与”、“或”、“非”参考1. 使用电信号的优势 从信息编码的角度来说&#xff0c;金、鼓、灯塔、烽火台类似电报的二进制编码。 电报传输的信号有两种&#xff0c;一种是短促的点信号&#xff08;dot 信号&#xff09;&#xff0c;…

【Go基础】包与工程化和常用标准库

文章目录一、包与工程化1. 用go mod管理工程2. 包引入规则3. init调用链4. 可见性二、常用标准库1. 数学计算2. 时间函数3. I/O操作4. 编码一、包与工程化 1. 用go mod管理工程 初始化项目&#xff1a; go mod init $module_name$module_name和目录名可以不一样 上述命令会生…

OpenMP 原子指令设计与实现

OpenMP 原子指令设计与实现 前言 在本篇文章当中主要与大家分享一下 openmp 当中的原子指令 atomic&#xff0c;分析 #pragma omp atomic 在背后究竟做了什么&#xff0c;编译器是如何处理这条指令的。 为什么需要原子指令 加入现在有两个线程分别执行在 CPU0 和 CPU1&…

LeetCode102_102. 二叉树的层序遍历

LeetCode102_102. 二叉树的层序遍历 一、描述 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff…

java抽象类和接口2023026

抽象类&#xff1a; 当编写一个类时&#xff0c;常常会为该类定义一些方法&#xff0c;这些方法用以描述该类的行为方式&#xff0c;那么这些方法都有具体的方法体。但在某些情况下&#xff0c;某个父类只是知道其子类应该包含怎样的方法&#xff0c;但无法准确地知道这些子类如…

使用阿里云服务器ECS 及一些问题白话阐述

阿里云服务器ECS的申请流程 首先登录阿里云官网 https://www.aliyun.com/ 查看产品文档学习观看然后看完后 大致有了了解后 我们按照我下面梳理的流程走首先购买阿里云服务器点击产品 下拉找到 云服务器ECS 然后点击进入进入到ECS的页面如果你是新人可以享受优惠购买因为还是比…