[023][x86汇编语言]习题12-1(修改本章代码清单,使之可以检测1MB以上的内存空间(从地址0x0010_0000开始,不考虑高速缓存的影响))
学习笔记
《x86汇编语言:从实模式到保护模式》习题12-1:修改本章代码清单,使之可以检测1MB以上的内存空间(从地址0x0010_0000开始,不考虑高速缓存的影响)。
https://www.jianshu.com/p/d481cb547e9f
- 要求:对内存的读写按双字的长度进行,并在检测的同时显示已检测的内存数量。建议对每个双字单元用两个花码
0x55AA55AA
和0xAA55AA55
进行检测。 - 分析:指定一块连续的内存区域,以双字为单元,写入
0x55AA55AA
再读出并与0x55AA55AA
比较,看是否相等;如果相等则,再写入0xAA55AA55
再再读出并与0xAA55AA55
比较,看是否相等;两次都相等,说明通过检测;
- 以双字为单元,利用两个花码反复写入读出来检测内存;
- 在屏幕上显示
已经通过检测的单元个数 / 需要检测的单元总数
(两个数值均以十六进制显示); - 每通过一次检测,屏幕上的字符 感叹号! 闪烁一次;
- 指定的内存区域全部检测通过后,在屏幕上显示字符串 "OK";
文章图片
习题12-1:修改本章代码清单,使之可以检测1MB以上的内存空间(从地址0x0010_0000开始,不考虑高速缓存的影响) 习题12-1:修改本章代码清单,使之可以检测1MB以上的内存空间(从地址0x0010_0000开始,不考虑高速缓存的影响 完整源码
;
代码清单12-1
;
文件名:ex12-1.asm
;
文件说明:硬盘主引导扇区代码
;
创建日期:16:23 2018/5/30;
---------------------------------------------------------------
;
定义常量
;
---------------------------------------------------------------
MEMORY_START equ 0x100000;
要检测的内存起始地址
MEMORY_ENDequ 0x500000;
要检测的内存结束地址
MEMORY_SIZEequ (MEMORY_END-MEMORY_START)/4;
以双字位单元
;
---------------------------------------------------------------;
设置堆栈段和栈指针
mov eax,cs
mov ss,eax
mov sp,0x7c00;
计算GDT所在的逻辑段地址
mov eax,[cs:pdgt+0x7c00+0x02];
GDT的32位线性基地址
xor edx,edx
mov ebx,16
div ebx;
分解成16位逻辑地址mov ds,eax;
令DS指向该段以进行操作:EAX低16位有效 DS=0x7e00
mov ebx,edx;
段内起始偏移地址:EDX EBX低16位有效 ebx=0x0000;
创建0#描述符,它是空描述符,这是处理器的要求
mov dword [ebx+0x00],0x00000000
mov dword [ebx+0x04],0x00000000;
创建1#描述符,这是一个数据段,对应0~4GB的线性地址空间
mov dword [ebx+0x08],0x0000ffff;
段基地址0x00000000
mov dword [ebx+0x0c],0x00cf9200;
创建2#描述符,这是一个只执行的代码段
mov dword [ebx+0x10],0x7c0001ff;
段基地址0x00007C00
mov dword [ebx+0x14],0x00409800;
创建3#描述符,这是上面代码段的别名
mov dword [ebx+0x18],0x7c0001ff;
段基地址0x00007C00
mov dword [ebx+0x1c],0x00409200;
创建4#描述符,这是栈段
mov dword [ebx+0x20],0x7c00fffe;
段基地址0x00007C00
mov dword [ebx+0x24],0x00cf9600;
初始化描述符寄存器GDTR
mov word [cs:pdgt+0x7c00],39;
5*8-1=39
lgdt [cs:pdgt+0x7c00]in al,0x92;
南桥芯片的端口
or al,0000_0010B
out 0x92,al;
打开A20climov eax,cr0
or eax,1
mov cr0,eax;
设置PE位;
以下进入保护模式... ...
jmp dword 0x0010:flush[bits 32]
flush:
mov eax,0x0018;
索引号3#
mov ds,eaxmov eax,0x0008;
索引号1#
mov es,eax
mov fs,eax
mov gs,eaxmov eax,0x0020;
索引号4#
mov ss,eax
xor esp,esp;
ESP=0mov dword [es:0x0b8000],0x072e0750;
'P.'
mov dword [es:0x0b8004],0x072e074d;
'M.'
mov dword [es:0x0b8008],0x07200720;
''
mov dword [es:0x0b800c],0x076b076f;
'ok';
---------------------------------------------------------------
;
显示需要检测的总的单元个数
;
---------------------------------------------------------------
mov byte [es:0x0b8140],'H'
mov byte [es:0x0b8142],'E'
mov byte [es:0x0b8144],'X'
mov byte [es:0x0b8146],':'mov ebp,0x0b8140+10
mov ecx,0
call checkmov byte [es:0x0b8140+30],'/'mov ebp,0x0b8140+34
mov ecx,MEMORY_SIZE
call check
;
---------------------------------------------------------------
;
内存检测
;
以双字为单元,使用花码0x55aa55aa和0xaa55aa55进行内存检测
;
---------------------------------------------------------------xor ecx,ecx;
检测的单元个数
mov ebx,MEMORY_START;
检测的起始地址
exam:
mov dword [es:ebx],0x55aa55aa
cmp dword [es:ebx],0x55aa55aa
jnz errmov dword [es:ebx],0xaa55aa55
mov dword [es:ebx],0xaa55aa55
jnz erradd ebx,4
inc ecx
mov byte[es:0x0b80a0+28],'!'
not byte[es:0x0b80a0+29]mov ebp,0x0b8140+10
call checkcmp ebx,MEMORY_END
jnz exammov dword [es:0x0b80b0+20],0x076b076f;
'ok';
---------------------------------------------------------------
err:
hlt;
进入停机状态;
---------------------------------------------------------------
;
子程序:check
;
参数:
;
ecx = 要显示的数值
;
ebp = 数值在显存的起始位置
;
功能:计算并显示检测的内存个数(以双字位单位)
;
---------------------------------------------------------------
check:push ebx
push ecx
push esi
push eax
push ebpmov eax,ecx
xor ebx,ebx
mov ecx,8
mov esi,16
digit:
xor edx,edx
div esi
mov [mem+ebx],dl
inc ebx
loop digitxor edi,edi
xor ebx,ebx
mov esi,7
show:
mov al,[mem+esi]
mov bl,al
mov al,[number+ebx]
mov [es:ebp+edi],al
add edi,2
dec esi
jns showpop ebp
pop eax
pop esi
pop ecx
pop ebxret
;
---------------------------------------------------------------
memdb0,0,0,0,0,0,0,0;
存放数位
numberdb '0123456789ABCDEF'
;
---------------------------------------------------------------
pdgtdw0
dd0x00007e00;
GDT的物理地址
;
---------------------------------------------------------------
times 510-($-$$) db 0
db 0x55,0xaa
代码说明
- 加载描述符部分以及进入保护模式与配书代码
c12_mbr.asm
完全一致
https://www.jianshu.com/p/7447a004fe7f
- 增加常量
;
---------------------------------------------------------------
;
定义常量
;
---------------------------------------------------------------
MEMORY_START equ 0x100000;
要检测的内存起始地址
MEMORY_ENDequ 0x500000;
要检测的内存结束地址
MEMORY_SIZEequ (MEMORY_END-MEMORY_START)/4;
以双字位单元
;
---------------------------------------------------------------
- 增加数据表,
mem表
存放数位,从number表
中取出每个数位对应的ASCII码
memdb0,0,0,0,0,0,0,0;
存放数位
numberdb '0123456789ABCDEF'
解题参考
- CSDN的这位博主还实现了一个很漂亮的进度条,提供的答案很棒!
https://blog.csdn.net/longintchar/article/details/50878960
- 代码整个结构(各个部分在内存中的映象)参考
https://www.jianshu.com/p/7447a004fe7f
- 子程序check的实现修改自书上第六章的显示各个数位
【[023][x86汇编语言]习题12-1(修改本章代码清单,使之可以检测1MB以上的内存空间(从地址0x0010_0000开始,不考虑高速缓存的影响))】https://www.jianshu.com/p/f71416ec68ac
推荐阅读
- 【023】我听好汉的
- [Py023]List元素重复
- 《我的修心奇迹日记》023
- #|阿尔法点亮LED灯(一)汇编语言
- x86架构应用如何向Arm架构低成本迁移
- 绘本讲师训练营【4期】|绘本讲师训练营【4期】 1/21 《他们都看见了一只猫》
- 20171023咖啡冥想
- 软工小白的First Blog
- android x86虚拟机 网络正确配置
- 【人生六大平衡践行】—-20191023第28天