本汇编代码对应保户模式下操作系统内核如何加载用户程序并运行 的实际主引导扇区代码:

  • 对应的内核代码在:内核代码
  • 对应的用户程序代码在:用户程序代码
         ;代码清单13-1;文件名:c13_mbr.asm;文件说明:硬盘主引导扇区代码 ;创建日期:2011-10-28 22:35        ;设置堆栈段和栈指针 core_base_address equ 0x00040000   ;常数,内核加载的起始内存地址 core_start_sector equ 0x00000001   ;常数,内核的起始逻辑扇区号 mov ax,cs      mov ss,axmov sp,0x7c00;计算GDT所在的逻辑段地址mov eax,[cs:pgdt+0x7c00+0x02]      ;GDT的32位物理地址 xor edx,edxmov ebx,16div ebx                            ;分解成16位逻辑地址 mov ds,eax                         ;令DS指向该段以进行操作mov ebx,edx                        ;段内起始偏移地址 ;跳过0#号描述符的槽位 ;创建1#描述符,这是一个数据段,对应0~4GB的线性地址空间mov dword [ebx+0x08],0x0000ffff    ;基地址为0,段界限为0xFFFFFmov dword [ebx+0x0c],0x00cf9200    ;粒度为4KB,存储器段描述符 ;创建保护模式下初始代码段描述符mov dword [ebx+0x10],0x7c0001ff    ;基地址为0x00007c00,界限0x1FF mov dword [ebx+0x14],0x00409800    ;粒度为1个字节,代码段描述符 ;建立保护模式下的堆栈段描述符      ;基地址为0x00007C00,界限0xFFFFE mov dword [ebx+0x18],0x7c00fffe    ;粒度为4KB mov dword [ebx+0x1c],0x00cf9600;建立保护模式下的显示缓冲区描述符   mov dword [ebx+0x20],0x80007fff    ;基地址为0x000B8000,界限0x07FFF mov dword [ebx+0x24],0x0040920b    ;粒度为字节;初始化描述符表寄存器GDTRmov word [cs: pgdt+0x7c00],39      ;描述符表的界限   lgdt [cs: pgdt+0x7c00]in al,0x92                         ;南桥芯片内的端口 or al,0000_0010Bout 0x92,al                        ;打开A20cli                                ;中断机制尚未工作mov eax,cr0or eax,1mov cr0,eax                        ;设置PE位;以下进入保护模式... ...jmp dword 0x0010:flush             ;16位的描述符选择子:32位偏移;清流水线并串行化处理器[bits 32]               flush:                                  mov eax,0x0008                     ;加载数据段(0..4GB)选择子mov ds,eaxmov eax,0x0018                     ;加载堆栈段选择子 mov ss,eaxxor esp,esp                        ;堆栈指针 <- 0 ;以下加载系统核心程序 mov edi,core_base_address mov eax,core_start_sectormov ebx,edi                        ;起始地址 call read_hard_disk_0              ;以下读取程序的起始部分(一个扇区) ;以下判断整个程序有多大mov eax,[edi]                      ;核心程序尺寸xor edx,edx mov ecx,512                        ;512字节每扇区div ecxor edx,edxjnz @1                             ;未除尽,因此结果比实际扇区数少1 dec eax                            ;已经读了一个扇区,扇区总数减1 @1:or eax,eax                         ;考虑实际长度≤512个字节的情况 jz setup                           ;EAX=0 ?;读取剩余的扇区mov ecx,eax                        ;32位模式下的LOOP使用ECXmov eax,core_start_sectorinc eax                            ;从下一个逻辑扇区接着读@2:call read_hard_disk_0inc eaxloop @2                            ;循环读,直到读完整个内核 setup:mov esi,[0x7c00+pgdt+0x02]         ;不可以在代码段内寻址pgdt,但可以;通过4GB的段来访问;建立公用例程段描述符mov eax,[edi+0x04]                 ;公用例程代码段起始汇编地址mov ebx,[edi+0x08]                 ;核心数据段汇编地址sub ebx,eaxdec ebx                            ;公用例程段界限 add eax,edi                        ;公用例程段基地址mov ecx,0x00409800                 ;字节粒度的代码段描述符call make_gdt_descriptormov [esi+0x28],eaxmov [esi+0x2c],edx;建立核心数据段描述符mov eax,[edi+0x08]                 ;核心数据段起始汇编地址mov ebx,[edi+0x0c]                 ;核心代码段汇编地址 sub ebx,eaxdec ebx                            ;核心数据段界限add eax,edi                        ;核心数据段基地址mov ecx,0x00409200                 ;字节粒度的数据段描述符 call make_gdt_descriptormov [esi+0x30],eaxmov [esi+0x34],edx ;建立核心代码段描述符mov eax,[edi+0x0c]                 ;核心代码段起始汇编地址mov ebx,[edi+0x00]                 ;程序总长度sub ebx,eaxdec ebx                            ;核心代码段界限add eax,edi                        ;核心代码段基地址mov ecx,0x00409800                 ;字节粒度的代码段描述符call make_gdt_descriptormov [esi+0x38],eaxmov [esi+0x3c],edxmov word [0x7c00+pgdt],63          ;描述符表的界限lgdt [0x7c00+pgdt]                  jmp far [edi+0x10]  ;-------------------------------------------------------------------------------
read_hard_disk_0:                        ;从硬盘读取一个逻辑扇区;EAX=逻辑扇区号;DS:EBX=目标缓冲区地址;返回:EBX=EBX+512 push eax push ecxpush edxpush eaxmov dx,0x1f2mov al,1out dx,al                       ;读取的扇区数inc dx                          ;0x1f3pop eaxout dx,al                       ;LBA地址7~0inc dx                          ;0x1f4mov cl,8shr eax,clout dx,al                       ;LBA地址15~8inc dx                          ;0x1f5shr eax,clout dx,al                       ;LBA地址23~16inc dx                          ;0x1f6shr eax,clor al,0xe0                      ;第一硬盘  LBA地址27~24out dx,alinc dx                          ;0x1f7mov al,0x20                     ;读命令out dx,al.waits:in al,dxand al,0x88cmp al,0x08jnz .waits                      ;不忙,且硬盘已准备好数据传输 mov ecx,256                     ;总共要读取的字数mov dx,0x1f0.readw:in ax,dxmov [ebx],axadd ebx,2loop .readwpop edxpop ecxpop eaxret;-------------------------------------------------------------------------------
make_gdt_descriptor:                     ;构造描述符;输入:EAX=线性基地址;      EBX=段界限;      ECX=属性(各属性位都在原始;      位置,其它没用到的位置0) ;返回:EDX:EAX=完整的描述符mov edx,eaxshl eax,16                     or ax,bx                        ;描述符前32位(EAX)构造完毕and edx,0xffff0000              ;清除基地址中无关的位rol edx,8bswap edx                       ;装配基址的31~24和23~16  (80486+)xor bx,bxor edx,ebx                      ;装配段界限的高4位or edx,ecx                      ;装配属性 ret;-------------------------------------------------------------------------------pgdt             dw 0dd 0x00007e00      ;GDT的物理地址
;-------------------------------------------------------------------------------                             times 510-($-$$) db 0db 0x55,0xaa

【OS学习笔记】二十 保护模式六:保户模式下操作系统内核如何加载用户程序并运行 对应的汇编代码之主引导扇区程序相关推荐

  1. 【OS学习笔记】二十二 保护模式六:保户模式下操作系统内核如何加载用户程序并运行 对应的汇编代码之用户程序

    本汇编代码对应文章:保户模式下操作系统内核如何加载用户程序并运行中的实际用户程序代码. 对应的主引导扇区代码:主引导扇区代码 对应的内核代码:内核代码 ;代码清单13-3;文件名:c13.asm;文件 ...

  2. 【OS学习笔记】二十一 保护模式六:保户模式下操作系统内核如何加载用户程序并运行 对应的汇编代码之内核代码

    本汇编代码对应文章保户模式下操作系统内核如何加载用户程序并运行 中的实际内核代码 对应的主引导扇区代码:主引导扇区代码 对应的用户程序代码:用户程序代码 ;代码清单13-2;文件名:c13_core. ...

  3. 【OS学习笔记】十九 保护模式六:保户模式下操作系统内核如何加载用户程序并运行

    上一篇文章学习了保户模式下如何进行内存保护 与 别名段的意义与作用:点击链接查看上一篇文章:点击链接 本文接着学习,在保护模式下,内核是如何加载用户程序并运行的.其实这与在实模式下很像,只不过现在保护 ...

  4. 【OS学习笔记】十六 保护模式四:进入保护模式与在保护模式下访问内存的汇编代码

    本文记录的是之前四篇文章所对应的汇编代码.四篇文章分别是: [OS学习笔记]十二 现代处理器的结构和特点 [OS学习笔记]十三 保护模式一:全局描述符表(GDT) [OS学习笔记]十四 保护模式二:段 ...

  5. 【OS学习笔记】十 实模式:实现一个程序加载器-程序加载器如何将用户程序加载到内存并执行

    上一篇文章学习了以下内容: 用一种不同的分段方法,从另一个不同的的角度理解处理器的分段内存访问机制 使用循环和条件转移指令来优化主引导扇区代码 点击链接查看上一篇文章:点击链接查看 对于主引导扇区部分 ...

  6. Mr.J-- jQuery学习笔记(二十八)--DOM操作方法(添加方法总结)

    Table of Contents appendTo appendTo(source, target) 源代码 append prependTo ​ ​ ​ ​ prependTo源码 prepend ...

  7. 嵌入式系统设计师学习笔记二十八:嵌入式程序设计③——高级程序设计语言

    嵌入式系统设计师学习笔记二十八:嵌入式程序设计③--高级程序设计语言 解释程序和编译程序 编译器的工作阶段示意图 语法错误:非法字符,关键字或标识符拼写错误 语法错误:语法结构出错,if--endif ...

  8. uniapp 学习笔记二十二 购物车页面结构搭建

    uniapp 学习笔记二十二 购物车页面结构搭建 cart.vue <template><view><view class="flex padding" ...

  9. Polyworks脚本开发学习笔记(二十)-补充几个常见操作指令的使用

    Polyworks脚本开发学习笔记(二十)-补充几个常见操作指令的使用 大概要写到结尾了,最后几篇就将手册的各常用命令再看一遍,组合一下,并列举出常见的一些有用的操作. DATA_COLOR_MAP数 ...

最新文章

  1. OpenGL学习(hello)
  2. android 中XML和对象转换利器Xstream的使用
  3. SQL 触发器的使用
  4. “约见”面试官系列之常见面试题之第六十七篇之jsonp原理和实现(建议收藏)
  5. Ubuntu8.04系列二-系统优化篇
  6. Centos 6 搭建安装 Gitlab
  7. 已设置的指纹解锁怎样解除_指纹锁哪个牌子更好用?
  8. Ztree 改 节点
  9. 上大计算机专业,高校“计算机”专业排行榜,东大完成逆袭,上交大不敌哈工大...
  10. 特大喜讯!鸿蒙项目来了:在线电子词典
  11. matlab画图常用符号,matlab画图特殊符号
  12. 怎么用odbc连接mysql数据库连接_怎么用odbc连接mysql数据库
  13. git项目提交报rejected问题解决
  14. JS间隔指定字符数后面插入
  15. B Spline(B样条曲线)
  16. 关于冯.诺依曼结构与哈佛结构的一些疑问
  17. Hololens学习(一)安装 部署Hololens开发环境
  18. 油菜花王国(并查集)
  19. 京东2020校招数据分析工程师二面(2019.9.18)
  20. 为什么AI公司都在一边融资,一边投资? | 甲子光年

热门文章

  1. 第二十七期:德国工业4.0眼里“工业互联网”与“智能制造”
  2. java学习(153):字符输出流
  3. java学习(41):成员实例的定义和访问续
  4. jenkins安装环境搭建(3)
  5. QT Openssl no OPENSSL_Applink 解决
  6. 使用 keytool 生成安卓应用程序签名
  7. 在deepin 15.5中安装vs code并配置c/c++环境
  8. Vmware下CentOs7 桥接模式下配置固定IP
  9. centos7下python3与python2共存并且开启py3虚拟环境
  10. EJB是什么?EJB的概念分析与理解(copy)