首页
社区
课程
招聘
[翻译]X86 汇编:真的是“恐怖”的存在吗?
发表于: 2018-10-15 21:01 7350

[翻译]X86 汇编:真的是“恐怖”的存在吗?

2018-10-15 21:01
7350

Assembly Language(汇编语言),对于哪些从未深入了解其中的人来说,可谓是高深莫测之极。由于我们的计算机是以汇编语言为基础开发出来的,了解这些内容将会极大地有助于我们弄清CPU的工作原理。

X86 计算机对 IBM PC 原生的完全后向兼容-从系统顶层到加电启动甚至底层硬件电路,实在是令人印象深刻。 这意味着几乎所有的 PC 都能运行1983年以后开发的软件;不过,需要为此付出的代价也是非常之高的。X86 架构由于它的 edge case 和复杂性而“名声大振”。

要明白一台现代 X86 计算机的启动过程,我们需要了解 X86 架构的发展历史,启动过程在 99%的情况下是由 bootloader 处理的。


在我们的 demo 中将专注于16位“实模式”-DOS系统和其他变种操作系统的运行环境。在该模式下,CPU并不支持现代操作系统所具有的各种安全保护措施。运行于其上的程序可以访问系统各个角落甚至修改系统。这使得 DOS 病毒大量泛滥(尽管这些病毒大都不具破坏性,但却很令人厌烦)。

在实模式下,与硬件交互的模型也极其简单。PC 通过外部丰富的软中断与各式各样的硬件交互。

这让使得最初的阶段的系统开发工作容易起来:因为开发者只需知道少许软中断即可完成绝大多数 I/O 操作。

了解这些之后,我们开始我们的第一个 demo:

上面的代码什么意思呢? 其中mov 指令是用来把数据从一个位置传送到另一个地方。在此,我们只是用来在寄存器间传送数据,并未涉及内存空
间。int 指令指代一系列软中断,在这段代码中是 16号中断。

接下来,既然我们已经执行完我们的任务,那么调用hlt指令停止 CPU 运行。

到现阶段,是不是有点疑惑,我们是怎么就执行到这一步了呢?计算机刚才又是如何执行这些指令的?

实际上,系统启动的第一阶段是启动 BIOS - 用于配置和检测系统硬件。同时, BIOS 输出系统信息给接下来启动的操作系统程序,以便于接下来的硬件检测工作。

假定 BIOS 知道它是从何种设备上启动,那么,它首先会加载该设备
的第一个扇区512字节到内存中的指定位置,然后跳转到此处将控制权移交给下一个启动程序。

在上面的 demo 中,程序仅读取了512字节的有效载荷。如果我们需要执行的程序超过512字节大小,怎么办呢?

有幸的是,BIOS 可以通过调用 13号 int 中断,来访问系统中的磁盘驱动器。

上述代码,加载虚拟磁盘的下一扇区 ,然后跳转到该处。13号 int 中断 API十分简洁,透露出计算机存储器工作的底层细节(尽管flsh存储器广泛使用,众多的数值依旧保留以保持兼容)。

BIOS 提供的服务极其的丰富,这有一个非常棒的参考资料:http://www.ctyme.com/intr/rb-0608.htm

希望这是进入 Assembly Language 的有趣开端,更多精彩,敬请期待 ......

磁盘 - 磁盘扇区写入参数定义

AH = 03h
AL = 写入的扇区数 (必须非零)
CH = 柱面数低8位
CL = 1-63扇区号 (bits 0-5)
柱面数的高2位 (6-7位, 只用于硬盘hard disk only)
DH = 磁头数
DL = 驱动器编号 (磁盘为硬盘驱动器时第7位置位)
ES:BX -> 数据缓冲区

返回值:
CF 写入错误时置位
CF 写入成功时清除置位
AH = 磁盘状态
AL = 传输的扇区数
(仅当某些BIOS的 CF 置位时有效 )

原文:https://blog.benjojo.co.uk/post/interactive-x86-bootloader-tutorial(文章略有删改)
翻译: 看雪翻译小组 StrokMitream
校对 :


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2019-2-2 15:35 被admin编辑 ,原因: 图片本地化
收藏
免费 1
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  junkboy   +1.00 2018/10/15
最新回复 (11)
雪    币: 11716
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
谢谢分享
2018-10-15 21:09
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
第2张图片里的"AI0"是什么意思? 难道不该是"A20"么?
2018-10-16 10:01
0
雪    币: 965
活跃值: (89)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢谢分享 
2018-10-16 15:39
0
雪    币: 32
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享
2018-10-17 15:52
0
雪    币: 0
活跃值: (150)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
感谢分享
2018-10-18 14:25
0
雪    币: 2734
活跃值: (801)
能力值: ( LV9,RANK:310 )
在线值:
发帖
回帖
粉丝
7
fengyunabc 第2张图片里的"AI0"是什么意思? 难道不该是"A20"么?
这个地方是 AIO(Asynchronous I/O,异步 I/O),不是 A “10” 
感谢大家的支持,欢迎大家对帖子内容提出质疑!
2018-10-19 23:17
0
雪    币: 278
活跃值: (1067)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8

mov al,1 //这里应该翻译为:将要读取的扇区数量

参考手册 原文:

DISK - READ SECTOR(S) INTO MEMORY
AH = 02h
AL = number of sectors to read (must be nonzero)
CH = low eight bits of cylinder number
CL = sector number 1-63 (bits 0-5)
high two bits of cylinder (bits 6-7, hard disk only)
DH = head number
DL = drive number (bit 7 set for hard disk)
ES:BX -> data buffer
2018-10-22 18:41
0
雪    币: 300
活跃值: (2477)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
mark
2018-10-22 21:49
0
雪    币: 204
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
thank you share
2018-10-23 14:29
0
雪    币: 2734
活跃值: (801)
能力值: ( LV9,RANK:310 )
在线值:
发帖
回帖
粉丝
11
青史无疆 # mov al,1 //这里应该翻译为:将要读取的扇区数量 参考手册 原文: --- ``` DISK - READ SECTOR(S) INTO MEMORY AH = 02h ...
多谢指正,已对原翻译进行修改!
2018-10-27 09:11
0
雪    币: 6064
活跃值: (12624)
能力值: ( LV12,RANK:312 )
在线值:
发帖
回帖
粉丝
12
谢谢分享 有机会研究一下 
原来看早版本Linux,好像0.11的内核 加电后由硬件强制cs:ip指向0xFFFF0地址 也就是BIOS 
0x00000~0x003FF是中断向量表
0x00400~0x004FF是BIOS数据区
借助int 19(0xE6F2), 然后读取软盘中的0盘面0磁道1扇区的512B 第一个启动扇区 加载到0x7C00处 然后复制到0x9000 
后面借助 int 13加载后面的扇区 从16位到32位启动的也是一个很奇妙的过程(实模式到保护模式)他会废除中断向量表 (将数据覆盖0x00000) 建立新GDTR IDTR等   A20也是标志性的地址(开启后将没有类似于回滚地址机制(16位)) 很多知识有些模糊 有机会在深入研究
不得不说真是艺术 多一个字节空闲的内存都没有
最后于 2018-11-17 09:25 被一半人生编辑 ,原因:
2018-11-17 09:17
0
游客
登录 | 注册 方可回帖
返回
//