[BITS 16]
org 07c00h ;org指令明确告诉编译器我程序开始地址是07c00h,而不是
;原来的00000
jmp main
gdt_table_start:
gdt_null:
dd 0h
dd 0h ;Intel 规定段描述表的第一个表项必须为0
gdt_data_addr equ $-gdt_table_start
gdt_data:
dw 07FFh ; 段界限
dw 0h ; 段基地址0~18位
db 0h ; 段基地址19~23位
db 10010010b ;段描述符的第六个字节属性(数据可读可执行)
db 11000000b ;段描述符的第七个字节属性
db 0 ;段描述符的最后一个字节也就是段基地址
gdt_video_addr equ $-gdt_table_start
gdt_video: ;用来描述显存地址空间的段描述符号
dw 0FFH ;显存段界限就是1M
dw 8000h
db 0Bh
db 10010010b
db 11000000b
db 0
gdt_code_addr equ $-gdt_table_start
gdt_code:
dw 07FFh ; 段界限(保持不变)
dw 1h ; 段基地址0~18位
db 80h ; 段基地址19~23位
db 10010010b ;段描述符的第六个字节属性(数据可读可执行)
db 11000000b ;段描述符的第七个字节属性
db 0 ;段基地址的第二部分
gdt_table_end:
gdtr_addr:
dw gdt_table_end-gdt_table_start-1 ;段描述表的长度
dw dt_table_start;段描述表基地
lgdt [gdtr_addr] ;让CPU读取 gdtr_addr所指向内存内
;A20地址线问题
main:
enable_a20:
in al,92h
or al,00000010b
out 92h,al
cli
;设置cro寄存器的第一位为1
mov eax,cro
or eax,1
mov cr0,eax
;跳转到保护模式中
jmp gdt_code_addr:0
[BITS 32]
;保护模式的功能就是屏幕中央打印hello world
data_32:
db "hello world"
code_32:
mov ax,gdt_data_addr
mov ds,ax
mov ax,gdt_video_addr
mov gs,ax
mov cx,11
mov edi,(80*10+12)*2 ;在屏幕中央显示
mov bx,0
mov ah,0ch
s:mov al,[ds:bx]
mov [gs:edi],al
mov [gs:edi+1],ah
inc bx
add edi,2
loop s
jmp $
tines $10-($-$$) db 0
dw 0aa$$h
接下来是用虚拟机Bochs for windows-console进行汇编代码调式:
用反汇编指令:disassemble
第一步: 开始输入反汇编测试下:disassemble 0x7c29 0x7c3c
调式过程中发现与我们写的汇编代码不一样,表出错了。
反思:到底我们那里出错了?