注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

编程学习

我的网上家园

 
 
 

日志

 
 

32位实模式测试代码  

2013-02-24 16:18:18|  分类: 《x86汇编语言: |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
32位实模式测试:
个人对于32位实模式的定义如下: CPU默认的指令译码方式为32位指令译码,当前按照32位指令执行;对于段存器的操作指令,传送到段寄存器的内容是段地址,不是保护模式下的段选择子.

;======================================================================================
先看下面的部分代码:
进入32位保护模式的代码省略,当前已经处于32位保护模式,然后执行以下指令:
                ;DS 基址0 段界限0xffffffff
mov ax,100_000B
mov ds,ax ;全局描述符表中的4#描述符,基地址为0 32位数据段,段界限0XFFFFFFFF

;测试32位实模式.
mov eax,cr0
and eax,0xfffffffe
mov cr0,eax

;通过JMP指令,刷新CS寄存器
jmp 0:0x7d33  ;real 加载到内存以后的地址是 0x7d33 手动计算的
               ;现在运行在32位实模式 
real:
mov eax,0
mov ds,eax ;刷新DS DS基址=0 段界限不变,还是在32位保护模式下的段界限
   ;实模式下,传送到段寄存器的值是 段地址
mov eax,message ;显示字符串
mov ch,10
xor ebx,ebx
real_show:
mov cl,[eax+0x7c00]
or cl,cl
jz ghalt
mov [0xb8140+ebx*2],cx
inc ebx
inc eax
jmp real_show
 ghalt:      hlt 

;============================================================================================
下面是全部的源代码:

         ;设置堆栈段和栈指针 
         mov ax,cs      
         mov ss,ax
         mov sp,0x7c00

         ;计算GDT所在的逻辑段地址 
         mov ax,[cs:gdt_base+0x7c00]            ;低16位 
         mov dx,[cs:gdt_base+0x7c00+0x02]   ;高16位 
         mov bx,16        
         div bx            
         mov ds,ax                          ;令DS指向该段以进行操作
         mov bx,dx                          ;段内起始偏移地址 
      
         ;创建0#描述符,空描述符
         mov dword [bx+0x00],0x00
         mov dword [bx+0x04],0x00  

         ;创建#1描述符,保护模式下的代码段描述符
 
 ;测试目的,基地址为0X7C00 段界限0xFFFFFFFF,只读,为了测试目的,设置较大段界限
         mov dword [bx+0x08],0x7c00ffff     
         mov dword [bx+0x0c],0x00cf9800     

         ;创建#2描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区) 
         mov dword [bx+0x10],0x8000ffff     
         mov dword [bx+0x14],0x0040920b     

         ;创建#3描述符,保护模式下的堆栈段描述符
         mov dword [bx+0x18],0x00007a00
         mov dword [bx+0x1c],0x00409600

 
;创建#4描述符,保护模式下的数据段 段基地址0 段界限0xFFFFFFFF
mov dword [bx+0x20],0xffff
mov dword [bx+0x24],0xcf9200
 
 
         ;初始化描述符表寄存器GDTR
         mov word [cs: gdt_size+0x7c00],39  ;描述符表的界限(总字节数减一)   
                                             
         lgdt [cs: gdt_size+0x7c00]
      
         in al,0x92                         ;南桥芯片内的端口 
         or al,0000_0010B
         out 0x92,al                        ;打开A20

         cli                                ;保护模式下中断机制尚未建立,应 
                                            ;禁止中断 
         mov eax,cr0
         or eax,1
         mov cr0,eax                        ;设置PE位
      
         ;以下进入保护模式... ...
         jmp 0x0008:flush             
                                            
         [bits 32] 

    flush:
         mov cx,00000000000_10_000B         ;加载数据段选择子(0x10)
         mov ds,cx

         ;以下在屏幕上显示"Protect mode OK." 
         mov byte [0x00],'P'  
         mov byte [0x02],'r'
         mov byte [0x04],'o'
         mov byte [0x06],'t'
         mov byte [0x08],'e'
         mov byte [0x0a],'c'
         mov byte [0x0c],'t'
         mov byte [0x0e],' '
         mov byte [0x10],'m'
         mov byte [0x12],'o'
         mov byte [0x14],'d'
         mov byte [0x16],'e'
         mov byte [0x18],' '
         mov byte [0x1a],'O'
         mov byte [0x1c],'K'

         ;以下用简单的示例来帮助阐述32位保护模式下的堆栈操作 
         mov cx,00000000000_11_000B         ;加载堆栈段选择子
         mov ss,cx
         mov esp,0x7c00

 
         mov ebp,esp                     ;保存堆栈指针 
         push byte '.'                      ;压入立即数(字节)
         
         sub ebp,4
         cmp ebp,esp                     ;判断压入立即数时,ESP是否减4 
         jnz ghalt                          
         pop eax
         mov [0x1e],al                    ;显示句点 
 
 
;DS 基址0 段界限0xffffffff
mov ax,100_000B
mov ds,ax
 
 
;测试32位实模式.
mov eax,cr0
and eax,0xfffffffe
mov cr0,eax

;通过JMP指令,刷新CS寄存器
jmp 0:0x7d33  ;real 加载到内存以后的地址是 0x7d33 手动计算的
       ;现在运行在32位实模式 
real:
mov eax,0
mov ds,eax ;刷新DS DS基址=0 段界限不变,还是在32位保护模式下的段界限
mov eax,message
mov ch,10
xor ebx,ebx
real_show:
mov cl,[eax+0x7c00]
or cl,cl
jz ghalt
mov [0xb8140+ebx*2],cx
inc ebx
inc eax
jmp real_show

  ghalt:     
         hlt                                ;已经禁止中断,将不会被唤醒 

;-------------------------------------------------------------------------------

message: db '32 real mode ok!',0
         gdt_size         dw 0
         gdt_base         dd 0x00007e00     ;GDT的物理地址 
                             
         times 510-($-$$) db 0
                          db 0x55,0xaa
;==================================================================================================
下面是运行截图:
32位实模式测试代码 - sangguowei2002 - 编程学习
 
  评论这张
 
阅读(87)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017