赞
踩
简单来说,每执行一次这个指令将会将一个描述内存区域的数据结构保存到ES:DI,然后返回一个ebx,用于确定下一个能够探测的内存区域,当ebx=0时,表示当前已经时最后一个内存区域了。那么ebx的初始值呢,就是设置成ebx=0。其中可能遇到检查发生错误的情况,这个指令就会直接将CF设置为1。
下图时输入时各个寄存器的作用:
| 寄存器 | 作用 |
|---|---|
| eax | 功能码,当输入e820h时能够探测内存 |
| ebx | 主要用于指向内存区域,第一次调用时ebx=0,被称为continuation value |
| es:di | 用于指令执行后,在指向的内存写入描述内存区域的数据结构ARDS(Address Range Descriptor Structure) |
| ecx | 用于限制指令填充的ARDS的大小,实际上大多数情况这个是无效的,无论ecx设置为多少,BIOS始终会填充20字节的ARDS |
| edx | 0534D4150h(‘SMAP’),输入时在edx,输出时将会在eax中 |
下面是输出时各个寄存器(标志)的结果:
| 寄存器 | 结果 |
|---|---|
| CF | 当没有发生错误时,CF=0,否则CF=1 |
| eax | 0534D4150h(‘SMAP’) |
| ebx | 指向下一个内存区域,而不是调用之前的内存区域,当ebx=0且CF=0时,表示当前是最后一个内存区域。 |
| es:di | 和调用之前一样,如果要保存多个ARDS,需要手动修改es:di |
| ecx | 返回写入的ARDS的大小 |
ARDS的结构(共20字节,Type为4字节)
| 偏移 | 名称 | 意义 |
|---|---|---|
| 0 | BaseAddrLow | 基地址的低32位 |
| 4 | BaseAddrHigh | 基地址的高32位 |
| 8 | LengthLow | 长度(字节)的低32位 |
| 12 | LengthHigh | 长度(字节)的高32位 |
| 16 | Type | 这个内存区域的类型 |
ARDS的Type取值如下:
| 取值 | 名称 | 意义 |
|---|---|---|
| 1 | AddressRangeMemory | 可以被OS使用的内存 |
| 2 | AddressRangeReserved | 正在使用的区域或者不能系统保留不能使用的区域 |
| 其他 | 未定义 | 各个具体机器会有不同的意义,在这里我们暂时不用关心,将它视为AddressRangeReserved即可 |
(好像csdn的汇编代码块高亮用不了,就只能这样了)
- ;当前处于实模式
- _MemChkBuf: times 256 db 0
- _dwMCRNumber: dw 0 ;记录ARDS的数量
- ...
- mov ebx,0
- mov di,_MemChkBuf ;请忽略es,假设已经正确设置好了
- .loop:
- mov eax,0e820h
- mov ecx,20
- mov edx,0534D4150h ;'SMAP'
- int 15h
- jc LABEL_MEM_CHK_FAIL ;检查CF,是否发生错误
- add di,20 ;由于执行INT 15h之后es和di不发生改变,就需要手动修改
- inc dword [_dwMCRNumber] ;记录ARDS的数量
- cmp ebx,0;判断是否到达最后一个内存区域
- jne .loop
- jmp LABEL_MEM_CHK_OK ;ebx=0到达最后一个内存区域
- LABEL_MEM_CHK_FAIL:
- mov dword [_dwMCRNumber],0
- LABEL_MEM_CHK_OK:

如果要读取就从开始es:di开始的地方开始逐个读取内存区域,得到的结果和这个类似
![]](https://img-blog.csdnimg.cn/20200830151440766.png#pic_center)
当然Linux上也有e820都差不多
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。