为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

保护模式下编程

2012-04-08 9页 doc 328KB 19阅读

用户头像

is_557733

暂无简介

举报
保护模式下编程保护模式下编程 ;1. ;=========================================================== ;在保护模式下32位CPU仍然可以用20位地址来实现32位地址线寻址 ;16位CPU: 16位段寄存器+16位偏移地址 (经地址加法器) -> 20位物理内存地址 ;32位CPU: 32位地址的内存段信息存入在一张内存表中,只需将表的索引存入16寄存器当中即可 ;保存表中索引的段寄存器称为:段选择子 ;表中每个表示32位内存段信息称为:段描述符(保存了段的地址和段的长度)。 ;...
保护模式下编程
保护模式下编程 ;1. ;=========================================================== ;在保护模式下32位CPU仍然可以用20位地址来实现32位地址线寻址 ;16位CPU: 16位段寄存器+16位偏移地址 (经地址加法器) -> 20位物理内存地址 ;32位CPU: 32位地址的内存段信息存入在一张内存表中,只需将表的索引存入16寄存器当中即可 ;保存表中索引的段寄存器称为:段选择子 ;表中每个表示32位内存段信息称为:段描述符(保存了段的地址和段的长度)。 ;整张表称为:段描述符表 ;段选择子16位,其中高13位用来表示描述符表中的索引,其低3位用表示段描述符中所指向的段描述符的属性 ; ;启动程序在屏幕中央打印一行字符串 [BITS 16] org 07c00h ;指明程序开始地址是07c00h,而不是原来 的00000 ;int 汇编指令 int 10h jmp main gdt_table_start: ;告诉编译器段描述符开始 ;Intel规定描述符表的第一个描述符必须是空描述符 gdt_null: dd 0h dd 0h ;Intel规定段描述符表的第一个表项必须为0 gdt_data_addr equ $-gdt_table_start ;数据段的开始位置 gdt_data: ;数据段描述符 dw 07ffh ;段界限 dw 0h ;段基地址18位 db 10010010b ;段描述符的第六个字节属性(数据段) db 1100000b ;段描述符的第七个字节属性 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 07ff ;段界限 dw 1h ;段基地址0~18位 db 80h ;段基地址19~23位 db 10011010b ;段描述符的第六个字节(代码段) db 11000000b ;段描述符的第七个字节 db 0 ;段基地址的第二部分 gdt_table_end: ;通过lgdt指令可以把GDTR描述表的大小和起始地址存入gdtr寄存器中 gdtr_addr: dw gdt_table_end-gdt_table_start-1 ;段描述表长度 dd gdt_table_start ;段描述表基地址 ;lgdt [gdtr_addr] ;让CPU读取gdtr_addr所指向内存内容保存到gdtr寄存器当中 ;A20地址线,切换到保护模式时,A20地址线必须开启。地址回绕作用,放弃32位CPU地址线的高12位。? ;端口的读写操作: ;in accume port ;将端口的内容读到寄存器AL或AX当中,其中accume只能是AL或AX。 ;out port accume ;将accume中的内容写到端口中,这里accume可以是其它寄存器 ;开启A20地址线 main: ;修改数据段描述跟段基地址有关的字节,初始化数据段描述符的基地址 xor eax,eax ;清空eax add eax,data_32 ;将32位地址信息拷贝到eax中 mov word [gdt_data+2],ax ;把ax中的内容拷贝到段描述符的第3、4两个字节当中,因是word类型的拷贝? shr eax,16 ;右移16位 mov byte [gdt_data+4],al ;将先前eax中的第5个字节移到段描述符当中 mov byte [gdt_data+7],ah ;将先前eax中的第8个字节移到段描述符当中 ;修改代码段描述跟段基地址有关的字节,初始化数据段描述符的基地址 xor eax,eax add eax,code_32 mov word [gdt_code+2] shr eax,16 mov byte [gdt_code+4],al mov byte [gdt_code+7],ah ;在转放保护模式之前,必须废除原来的中断向量表,用cli指令可以废除实模式下的中断向量表 cli lgdt [gdtr_addr] ;让CPU读取gdtr_addr所指向内存内容保存到gdtr寄存器当中 enable_a20: in al,92h ;只要往0x92号端口中写入信息就可以开启A20地址线 or al,00000010b ;00000010表示开启A20地址线的数据 out 92h,al ;把设置好的数据写进0x92号端口当中 ;转入保护模式,只要将CR0寄存器的第1位(PE位)置为1即可 ;80386提供了4个32位的控制寄存器CR0~CR3,其中CR0中的某些位是用来标志是否要进入保护模式 ;CR1寄存器保留没有被使用 ;CR2和CR3用于分页机制 ;CR0的PE位控制分段管理机制,PE=0,CPU运行于实模式;PE=1,CPU运行于保护模式 ;CR0的PG位控制分段管理机,PG=0,禁止分页管理机制;PG=1,启用分页管理机制。 mov eax,cr0 or eax,1 ;用于把CR0寄存器的第1置为1 mov cr0,eax ;把CR0寄存器的第1置为1 ;跳转到保护模式中 jmp gdt_code_addr:0 ;在保护模式下编程(在屏幕中央打印hello world) [BITS 32] 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] mov [gs:edi+1],ah inc bx add edi,2 loop s jmp $ ;死循环 times 510-($-$$) db 0 dw 0aa55h ;ok ! ^_^ ;1.启动虚拟机,用nasm boot.asm -o boot.bin 编译 ;2.把程序写到软盘镜像里去,用编译好的写入文件程序写入: ./write_image boot.bin boot.img ;3.将boot.img复制到自己在Bochs-2.4.6目录下建的文件夹下,并修改run.bat ;----------------------------------------------- ;其中write_image.c,可以在rad hat的vi编辑器这样写:? #include #include #include #include int main(int argc,char *argv[]) { int fd_source; int fd_dest; int read_count=0; char buffer[512]={0}; fd_source=open("boot.bin",O_RDONLY); IF(fd_source<0) { perror("open boot.bin error"); return 0; } fd_dest=open("virtual_floppy.vfd",O_WRONLY); while ((read_count=read(fd_source,buffer,512))>0) { write(fd_dest,buffer,read_count); memset(buffer,0,512); } printf("wrinte image OK !"); return 0; } ;保存成write_image.c,然后编译:gcc write_image.c -o write_image ;用虚拟软盘制作工具,制作一个虚拟软盘(取名boot.img),最后再用它将引导程序写入boot.img ; ^_^ ok! ;启动程序有问题的话,可以用bocsh虚拟机对操作系统进行调试。 ;=================================================== ;bocsh的调试功能bocshdbg ; continue(c) 程序继续运行直到遇到断点为止 ; step(s) 音步跟踪 ; vbreak(vb) 在虚拟地址上设置一个断点 ; pbreak(b) 在物理地址上设置一个断点 ; lbreak(lb) 在线性地址上设置一个断点 ; disassemble 反汇编指令 ;================================================================ ;================================================================ ;2. 一个在屏幕中央显示一行字符串的引导程(实模式下写) ;启动程序在屏幕中央打印一行字符串 org 07c00h ;指明程序开始地址是07c00h,而不是原来 的00000 ;int 汇编指令 int 10h mov ax,cs mov es,ax mov bp,msgstr ;es:bp指向的内容就是我们要显示的字符串地址? mov cx,12 ;字符串长度 mov dh,12 ;显示起始行号 mov dl,36 ;显示的列号 mov bh,0 ;显示的页数,在第0页显示 mov al,1 ;串结构 mov bl,0c ;黑底红字 msgstr: db "hello my os" int 10h ;BIOS中断 times 510-($-$$) db 0 ;重复N次每次填充值为0 ;因为BIOS的第一个扇区是512字节,当最后两字节是55AA时,它就是引导程序? dw 55aaH jmp $ ;为了不让程序结束,设置一个死循环,不断跳转到当前位置? ;在Linux操作系统下,用nasm 进行编译,命令:# nasm boot.asm -o boot.bin ;用 ndisasm boot.bin 可以进行反编译 注:引自大灰狼之视频教程《零基础汇编汇编视频课程》
/
本文档为【保护模式下编程】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索