学习笔记
《x86汇编语言:从实模式到保护模式》
https://www.jianshu.com/p/d481cb547e9f
代码参考
- 配书代码
c12_mbr.asm
运行结果
内存映象
完整源码
;代码清单12-1
;文件名:code_12.asm
;文件说明:硬盘主引导扇区代码
;创建日期:14:08 2018/5/30
;设置堆栈段和栈指针
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 ;打开A20
cli
mov eax,cr0
or eax,1
mov cr0,eax ;设置PE位
;以下进入保护模式... ...
jmp dword 0x0010:flush
[bits 32]
flush:
mov eax,0x0018 ;索引号3#
mov ds,eax
mov eax,0x0008 ;索引号1#
mov es,eax
mov fs,eax
mov gs,eax
mov eax,0x0020 ;索引号4#
mov ss,eax
xor esp,esp ;ESP=0
mov dword [es:0x0b8000],0x072e0750 ;'P.'
mov dword [es:0x0b8004],0x072e074d ;'M.'
mov dword [es:0x0b8008],0x07200720 ;' '
mov dword [es:0x0b800c],0x076b076f ;'ok'
;冒泡排序
mov ecx,pdgt-string-1 ;遍历次数=串的长度-1
@@1:
push ecx ;32位模式下的loop使用ecx
xor bx,bx ;32位模式下,偏移量可以使16位或者32位
@@2:
mov ax,[string+bx]
cmp ah,al
jge @@3
xchg al,ah
mov [string+bx],ax
@@3:
inc bx
loop @@2
pop ecx
loop @@1
;显示排序后的字符串
mov ecx,pdgt-string
xor ebx,ebx ;偏移地址是32位
@@4:
mov ah,0x07
mov al,[string+ebx]
mov [es:0xb80a0+ebx*2],ax ;比例因子
inc ebx
loop @@4
hlt ;进入停机状态
;---------------------------------------------------------------
string db 's0ke4or92xap3fv8giuzjcy5l1m7hd6bnqtw.'
;---------------------------------------------------------------
pdgt dw 0
dd 0x00007e00 ;GDT的物理地址
;---------------------------------------------------------------
times 510-($-$$) db 0
db 0x55,0xaa
代码说明
要 写 只执行的代码段,需要一个指向同区域的 别名 数据段;
段描述符格式、段选择子格式、索引号求法 参考
https://www.jianshu.com/p/0ec493a0287c
https://www.jianshu.com/p/1d0c583cd46f