操作系统真相还原第五章------获取内存大小参数

教材里采用了三种方式获取内存的参数,这里我只用了一种方法,那就是int 0x15中断的0xe820方式。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

内存读取程序:
xor ebx,ebx
mov edx,0x534d4150
mov di,ards_buf ;ards_buf 返回结构的存储地址
e820_mem_get_loop:
mov eax,0x0000e820 ;因为每次返回值会覆盖eax,所以需要重新赋值
mov ecx,20
int 0x15
add di,cx ;内存增加,为下一次保存留出空间,防止覆盖上一次的保存值
inc word [ards_nr] ;读取的次数,保存在ards_nr地址处
cmp ebx,0 ;如果ebx为0,说明读取完毕
jnz e820_mem_get_loop

;load.S程序源码
%include “boot.inc”
section loader vstart=LOADER_BASE_ADDR
LOADER_STACK_TOP equ LOADER_BASE_ADDR
jmp start

GDT_START: dd 0x00000000
dd 0x00000000

CODE_DESC: dd 0x0000FFFF
dd CODE_HIGH4
STACK_DATA_DESC: dd 0x0000FFFF
dd DATA_HIGH4
VIDIO_DESC: dd 0x80000007
dd VIDIO_HIGH4

GDT_SIZE equ $-GDT_START
GDT_LIMIT equ GDT_SIZE-1
times 60 dq 0

;段选择子创建
SELECT_CODE equ (0x0001<<3)+TI_GDT+RPL0
SELECT_DATA equ (0x0002<<3)+TI_GDT+RPL0
SELECT_VIDIO equ (0x0003<<3)+TI_GDT+RPL0

;total_mem_bytes 用于保存内存容量,以字节为单位,此位置比较好记
total_mem_bytes dd 0
ards_buf times 241 db 0
ards_nr dw 0

gdt_ptr dw GDT_LIMIT
dd GDT_START

start:
xor ebx,ebx
mov edx,0x534d4150
mov di,ards_buf
e820_mem_get_loop:
mov eax,0x0000e820
mov ecx,20
int 0x15
add di,cx
inc word [ards_nr]
cmp ebx,0
jnz e820_mem_get_loop
mov cx,[ards_nr]
mov ebx,ards_buf
xor edx,edx
find_max_mem_loop:
mov eax,[ebx]
add eax,[ebx+8]
add ebx,20
cmp edx,eax
jge next
mov edx,eax
next:
loop find_max_mem_loop

mov [total_mem_bytes],edx

in al,0x92
or al,0000_0010B
out 0x92,al

lgdt [gdt_ptr]

mov eax,cr0
or eax,0x00000001
mov cr0,eax

jmp dword SELECT_CODE:mode_start
[bits 32]
mode_start:
mov ax,SELECT_DATA
mov ds,ax
mov es,ax
mov ss,ax
mov esp,LOADER_STACK_TOP
mov ax,SELECT_VIDIO
mov gs,ax

mov byte [gs:160],‘P’
jmp $

在原书中,采用的是将total_mem_bytes地址凑成0xb00,start地址为相对于本文件起始偏移为0x300,但是我没有省去jmp start ,所以将使用ards_buf times 241 db 0 保证了 start地址为相对于本文件起始偏移为0x300,但此时total_mem_bytes地址为0xb003.
在这里插入图片描述

发布了24 篇原创文章 · 获赞 3 · 访问量 930

猜你喜欢

转载自blog.csdn.net/HIT_zhanmusi/article/details/103103558