调试一天半,复刻成功!!!

;文件名:Program_Loader.asm
;文件说明:硬盘主引导扇区代码(加载程序)
;创建日期:2021-11-1;用户程序起始逻辑扇区号
;段
;Main:
;设置堆栈
;计算用户程序加载的段地址
;设置程序读取的上文(先读取一个扇区,获取基本信息)
;利用基本信息,计算程序的总扇区数
;(若剩余扇区数>0)读取剩余扇区
;重置段表
;跳转至用户程序入口
;
;
application equ 10                             ;用户程序所在扇区号
section app_load align=16 vstart=0x7c00;设置堆栈指针
mov ax,0
mov ss,ax
mov sp,0x0;设置用户程序加载位置
mov ax,[cs:phy_base]                          ;低位
mov dx,[cs:phy_base+0x2]                      ;高位
mov bx,0x10
div bx
mov ds,ax                                     ;ds与es指向用户程序加载位置
;mov es,ax;读取一个扇区大小的用户程序
mov di,0                                      ;扇区读取目标地址ds:di
mov si,application                            ;需读取扇区号
call read_HardDisk_0                          ;开始读取;计算用户程序大小
mov dx,[0x2]                                  ;用户程序大小高地址
mov ax,[0x0]                                  ;用户程序大小低地址
mov bx,512                                    ;一个扇区大小
div bx                                        ;ax为商,dx为余
cmp dx,0x0                                    ;ax:所占用完整的扇区数
jnz @1                                        ;dx为0,则共需读取ax个扇区(别忘了已经读取过一个扇区)
dec ax                                        ;dx不为0,则共需读取ax+1个扇区(别忘了已经读取过一个扇区);判断用户程序所占扇区大小
@1:                                           ;若ax为0,则无需再读取
cmp ax,0
jz re_entrymov cx,ax                                     ;读取剩余扇区的程序
@2:                                           ;此时di=512,ds=0x10000
inc si                                        ;si为需读取扇区号
call read_HardDisk_0                          ;读取第si个扇区
loop @2;用户程序读取完毕;用户程序起始地址:0x10000
re_entry:                                     ;重置用户程序代码入口
mov dx,[0x8]                                  ;代码段入口高地址
mov ax,[0x6]                                  ;代码段入口低地址
call translaion_address                       ;返回段地址ax
mov [0x6],ax                                  ;重写程序入口段基址mov di,  0xc                                  ;段基址重定位表首地址
mov cx,[0xa]                                  ;需重置段基址数量
re_section:
mov dx,[di+0x2]                               ;代码段入口高地址
mov ax,[di]                                   ;代码段入口低地址
call translaion_address                       ;返回段地址ax
mov [di],ax                                   ;重写程序入口段基址
add di,4                                      ;下一需重定位段基址
loop re_sectionjmp far [0x4]                                ;跳转至用户程序入口
;----------------------------------------------------------------------------------
;硬盘读取
read_HardDisk_0:                              ;si为所需扇区号;ds:di为目标地址
push cxmov al,0x1                                    ;读取扇区数
mov dx,0x1f2                                  ;0x01f2端口
out dx,al
inc dx;0x01f3端口,0x01f4端口,0x01f5端口,0x01f6端口
;LBA地址0~7,LBA地址8~15,LBA地址16~23,LBA地址24~27
;0~27:LBA28逻辑扇区
;28~31:
;28:[0:主硬盘/1:从硬盘]
;29~31:[101:CHS/111:LBA]mov ax,si
out dx,al                                     ;0x01f3端口,LBA地址0~7
inc dxmov al,0x0
out dx,al                                     ;0x01f4端口,LBA地址8~15
inc dxout dx,al                                     ;0x01f5端口,LBA地址16~23
inc dxmov al,0xe0
out dx,al                                     ;0x01f6端口,LBA地址24~27
inc dx                                        ;28~31,模式设置mov al,0x20
out dx,al                                     ;0x01f7端口,向端口写入0x20(写命令);等待硬盘数据准备
wait_:
in al,dx                                      ;0x01f7端口为状态寄存器
and al,0x88                                   ;留下第7位,第4位
cmp al,0x8                                    ;第7位为0表示不忙,第4位为1表示数据以准备好
jnz wait_mov dx,0x1f0                                  ;数据传送端口
mov cx,256;开始读取硬盘                                 ;读取字数
read_:
in ax,dx
mov [di],ax
inc di
inc di
loop read_pop cxret
;--------------------------------------------------------------------------------------
translaion_address:                           ;输入;dx为16位高地址(2B);ax为16位低地址(2B);phy_base=0x10000(4B)
add ax,[cs:phy_base]                          ;低位相加,CF进位
adc dx,[cs:phy_base+0x2]                     ;高位相加,加上CF进位,由此完成32位加法;此时dx:ax为内存中入口点代码段起始地址;8086中仅有20位地址线(前20位有效);所以dx:ax仅有20位有效;因为ax有16位有效;于是dx虽有16位,dx仅有最后4位有效;只取20位中高16位作为段地址
shl dx,12                                     ;dx低4位放于高4位返回
shr ax,4                                      ;保留ax高12位放于低12位返回
add ax,dx                                     ;返回段地址axret
;----------------------------------------------------------------------------------
phy_base dd 0x10000                           ;用户程序加载位置,16字节对齐
db 510-($-$$) dup(0)                          ;补充满一个扇区
db 0x55,0xaa

x86汇编从实模式到保护模式-程序加载器相关推荐

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

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

  2. 【OS修炼指南目录】----《X86汇编语言-从实模式到保护模式》读书笔记目录表

    学习交流加(可免费帮忙下载CSDN资源): 个人微信: liu1126137994 学习交流资源分享qq群1(已满): 962535112 学习交流资源分享qq群2: 780902027 本文是将个人 ...

  3. 硬盘和显卡的访问与控制(一)——《x86汇编语言:从实模式到保护模式》读书笔记01

    本文是<x86汇编语言:从实模式到保护模式>(电子工业出版社)的读书实验笔记. 这篇文章我们先不分析代码,而是说一下在Bochs环境下如何看到实验结果. 需要的源码文件 第一个文件是加载程 ...

  4. 程序的加载和执行(六)——《x86汇编语言:从实模式到保护模式》读书笔记26

    程序的加载和执行(六)--<x86汇编语言:从实模式到保护模式>读书笔记26 通过本文能学到什么? NASM的条件汇编 用NASM编译的时候,通过命令行选项定义宏 Makefile的条件语 ...

  5. 程序的加载和执行(一)——《x86汇编语言:从实模式到保护模式》读书笔记21

    程序的加载和执行(一) 本文及之后的几篇博文是原书第13章的学习笔记. 本章主要是学习一个例子,对应的代码分为3个文件: ;代码清单13-1;文件名:c13_mbr.asm;文件说明:硬盘主引导扇区代 ...

  6. 进入保护模式(二)——《x86汇编语言:从实模式到保护模式》读书笔记14

    首先来段题外话:之前我发现我贴出的代码都没有行号,给讲解带来不便.所以从现在起,我要给代码加上行号.我写博客用的这个插入代码的插件,确实不支持自动插入行号.我真的没有找到什么好方法,无奈之下,只能按照 ...

  7. X86汇编语言从实模式到保护模式20:平坦模型

    1 引入平坦模型(Flat Model)的原因 1.1 内存管理模型变迁 1.1.1 分段模型 1.1.1.1 基本特点 1. 在程序中按结构组织为多个段 2. 在加载程序时,为程序中的每个段创建段描 ...

  8. X86汇编语言从实模式到保护模式13:保护模式程序的动态加载和执行

    目录 1. 引入保护模式对程序加载与执行的影响 1.1 对应用程序的影响 1.2 对操作系统的影响 1.3 本章程序总体结构 2. MBR加载内核过程分析 2.1 内核头部段分析 2.1.1 内核总长 ...

  9. X86汇编语言从实模式到保护模式11:指令格式及操作尺寸

    目录 1. 80286的16位保护模式 1.1 80286寄存器 1.2 80286段描述符 1.3 80286保护模式内存访问 2. 指令操作尺寸 2.1 指令操作尺寸的概念 2.2 16位处理器的 ...

最新文章

  1. SmartGridView(VB)
  2. jQuery用于请求服务器的函数
  3. (转载)Xcode中other linker flags的作用
  4. python3 numpy. ndarray 与 list 互转方法
  5. css grid 自动高度_2020年你不应该错过的CSS新特性(二)
  6. ext3文件系统反删除利器-ext3grep
  7. patch -p0 和patch -p1的区别
  8. 强碱性食品 高嘌呤食物
  9. 《多核与GPU编程:工具、方法及实践》----1.5 并行程序性能的预测与测量
  10. ots在线考计算机的word,ots在线考试系统1(OTS online examination system 1).doc
  11. .NET Core 跨平台物联网框架 ServerSuperIO.Core,一套设备驱动通吃嵌入式、上位机、云服务...
  12. ENVI图像纹理提取
  13. Dbgview.exe输出Windows程序调试信息
  14. 计算机地图制图符号制作的心得,计算机地图制图原理与方法——地图符号设计参考文档...
  15. 排序算法图解(一):冒泡排序与冒泡排序的优化
  16. java调用后台的短信验证码_JAVA通过http调用验证码短信接口源码
  17. [电子电路基础] 如何区分LED发光二极管引脚的正负极
  18. 详解Nginx Rewrite标记last和break的区别
  19. self.view.window, self.view.superView的意思
  20. Nginx负载均衡是酱紫做的

热门文章

  1. 用C语言写的迅雷看看XV文件提取器及C语言源代码
  2. hdu_1233(最小生成树)
  3. VBA实战技巧精粹012:查找指定目录下的指定文件及Dir函数用法
  4. 提升 .NET 程序性能的 一些 原则
  5. 详解spl_autoload_register()函数
  6. OpenGL ES之GLSL自定义着色器编程实现粒子效果
  7. LeetCode Algorithm 386. 字典序排数
  8. python人工智能——深度学习——TensorFlow基本介绍
  9. 《算法竞赛入门经典》习题3-1 得分(Score,ACM、ICPC Seoul 2005,UVa1585)
  10. Linux下多窗口分屏式终端--Terminator