x86汇编语言 编写64位多处理器多线程操作系统
全新正版 极速发货
¥
82.37
6.4折
¥
128
全新
库存19件
作者李忠,王晓波,李双圆
出版社电子工业出版社
ISBN9787121479083
出版时间2024-06
装帧平装
开本16开
定价128元
货号1203286562
上书时间2024-07-02
商品详情
- 品相描述:全新
- 商品描述
-
目录
第1章 基本要求和相关说明1
1.1 配书代码和工具1
1.2 NASM的下载和安装1
1.3 NASMIDE的下载和使用3
1.4 下载和安装VirtualBox7
1.5 使用FixVhdWr将程序写入虚拟硬盘8
1.6 本书的代码组织10
第2章 x64架构的基本执行环境37
2.1 x64架构的由来37
2.2 物理地址、有效地址和线性地址39
2.3 x64架构的工作模式40
2.3.1 x86处理器的工作模式40
2.3.2 IA-32e模式及其子模式41
2.4 x64架构的寄存器43
2.4.1 x64架构对通用寄存器的扩展43
2.4.2 x64架构的通用寄存器访问规则45
2.5 x86处理器的物理地址空间46
2.6 传统模式的内存访问47
2.6.1 传统模式下的线性地址和物理地址47
2.6.2 传统模式下的32位4KB分页技术48
2.6.3 传统模式下如何利用超过4GB的物理内存49
2.6.4 传统模式下的32位4MB分页技术50
2.6.5 传统模式下的32位PAE分页技术52
2.6.6 传统模式下的32位PAE-4KB分页技术52
2.6.7 传统模式下的32位PAE-2MB分页技术54
2.7 IA-32e模式的内存访问56
2.7.1 x64架构的线性地址空间56
2.7.2 扩高(Canonical)地址57
2.7.3 扩高地址的特点和处理器检查58
2.7.4 兼容模式的内存访问59
2.7.5 64位模式的内存访问60
2.7.6 x64架构的段寄存器60
2.7.7 x64架构的代码段描述符61
2.7.8 x64架构的数据段描述符62
2.7.9 x64架构的4级和5级分页63
2.8 x64架构的系统表和系统描述符65
2.8.1 x64架构的GDTR65
2.8.2 x64架构的IDTR66
2.8.3 x64架构的LDT描述符和LDTR67
2.8.4 x64架构的TSS描述符和TR68
2.9 x64架构的标志寄存器和指令指针寄存器69
2.10 x64架构的寻址方式71
2.10.1 x64架构下传统模式的寻址方式71
2.10.2 x64架构下IA-32e模式的寻址方式72
2.10.3 64位模式的RIP相对寻址方式73
2.10.4 64位模式下的指令变化情况75
2.11 IA-32e模式下的中断和异常处理概述77
第3章 进入IA-32e模式79
3.1 如何进入IA-32e模式79
3.2 本章代码清单81
3.3 执行主引导程序101
3.3.1 NASM的文件包含101
3.3.2 主引导程序的说明102
3.3.3 用BIOS硬盘扩展读加载内核加载器103
3.3.4 通过数据段访问栈中的数据结构106
3.3.5 读取内核加载器程序的剩余部分107
3.3.6 转入内核加载器执行109
3.4 执行内核加载器110
3.4.1 检测处理器是否支持IA-32e模式110
3.4.2 位测试指令BT111
3.4.3 获取处理器的商标和地址尺寸111
3.5 进入保护模式115
3.6 加载内核程序118
3.7 为进入IA-32e模式准备4级分页121
3.7.1 2MB和1GB页面的4级分页方式122
3.7.2 4级头表的格式123
3.7.3 页目录指针项的格式125
3.7.4 页目录项和页表项的格式127
3.7.5 4级头表的创建和初始化129
3.7.6 创建指向4级头表自身的4级头表项129
3.7.7 准备映射物理内存的低端2MB空间130
3.7.8 创建与低端2MB物理内存对应的分页系统表项132
3.7.9 将物理内存低端的2MB映射到线性地址空间的高端134
3.7.10 为多任务环境准备必要的4级头表项136
3.7.11 为多任务环境预分配254个页目录指针表137
3.7.12 进程上下文标识PCID139
3.7.13 控制寄存器CR3的内容格式140
3.7.14 设置控制寄存器CR3并开启物理地址扩展功能141
3.7.15 型号专属寄存器IA32_EFER的设置和分页的开启142
3.8 进入IA-32e的兼容模式执行143
3.9 进入64位模式的内核执行144
3.10 让内核工作在线性地址空间的高端145
3.10.1 启用GDT和栈区的高端线性地址146
3.10.2 使用RIP相对寻址方式计算内核的高端线性地址147
3.10.3 让处理器转到内核程序对应的高端位置继续执行148
3.11 初始化IA-32e模式下的中断系统149
3.11.1 IA-32e模式下的中断门和陷阱门149
3.11.2 IA-32e模式下的中断处理过程151
3.11.3 通用的中断和异常处理策略152
3.11.4 通用异常服务例程的工作过程152
3.11.5 加载有效地址指令LEA155
3.11.6 创建通用异常处理过程的中断门156
3.11.7 安装通用异常处理过程的中断门157
3.11.8 安装通用中断处理过程的中断门159
3.11.9 初始化8259中断控制器159
3.11.10 打印64位模式下的第一条信息160
3.12 本章代码的编译和运行162
第4章 单处理器环境下的多任务管理和调度164
4.1 本章代码清单165
4.2 初始化快速系统调用环境182
4.2.1 快速系统调用的原理182
4.2.2 为快速系统调用安装段描述符184
4.2.3 为快速系统调用准备段选择子186
4.2.4 设置快速系统调用的入口点187
4.2.5 快速系统调用时的RFLAGS和栈切换188
4.3 动态内存分配189
4.3.1 内核空间的分配策略189
4.3.2 内核可用线性地址的获取和更新190
4.3.3 立即数在64位模式下的长度192
4.3.4 计算本次内存分配涉及的线性地址范围193
4.3.5 获取与指定线性地址对应的4级头表项的线性地址193
4.3.6 页面分配与页映射位串196
4.3.7 页映射位串的定义和空闲页的查找197
4.3.8 获取与指定线性地址对应的页目录指针项的线性地址199
4.3.9 检查与指定线性地址对应的页目录指针项是否存在201
4.3.10 分配页目录表并安装与线性地址对应的页目录指针项201
4.3.11 安装与指定线性地址对应的页目录项、页表项和页面202
4.4 创建并安装TSS描述符203
4.4.1 LDT和TSS描述符的格式204
4.4.2 创建和安装64位的TSS描述符并加载任务寄存器TR205
4.5 初始化实时时钟中断206
4.6 创建外壳任务207
4.6.1 准备创建外壳任务207
4.6.2 为新任务创建任务控制块PCB208
4.6.3 为新任务创建4级头表209
4.6.4 将指定的线性地址映射到指定的物理页211
4.6.5 复制当前活动4级头表的内容给新任务的4级头表212
4.6.6 切换到新任务的地址空间并清空4级头表的前半部分212
4.6.7 为新任务分配0特权级使用的栈空间213
4.6.8 为新任务分配3特权级使用的栈空间214
4.6.9 从硬盘上加载用户程序215
4.6.10 生成任务标识216
4.6.11 将新任务的PCB添加到PCB链表217
4.6.12 设置外壳任务的状态220
4.7 设置任务状态段TSS220
4.8 转到外壳任务的局部空间执行221
4.9 快速系统调用的进入和返回222
4.9.1 为快速系统调用指定功能号223
4.9.2 根据功能号计算内核例程的线性地址223
4.9.3 快速系统调用的返回和指令前缀REX225
4.10 利用实时时钟中断执行任务切换226
4.10.1 查找处于就绪状态的任务226
4.10.2 任务切换的执行过程227
4.11 外壳任务的执行过程229
4.11.1 通过系统调用获取屏幕上可用的显示行坐标229
4.11.2 通过系统调用获取当前时间230
4.11.3 在外壳任务中显示当前时间231
4.12 用户任务的创建和执行232
4.12.1 当前任务标识的获取233
4.12.2 用户程序例程库的介绍233
4.12.3 将64位二进制数转换为十进制字符串234
4.12.4 在每轮相加中将结果和加数转换为字符串235
4.12.5 字符串的连接和显示236
4.12.6 用户任务的终止236
4.13 本章程序的编译和执行238
第5章 多处理器和APIC的初始化240
5.1 多处理器环境概述240
5.2 同时多线程和INTEL超线程技术241
5.3 高级可编程中断控制器APIC243
5.3.1 中断引脚、中断类型和中断源245
5.3.2 本地中断源和本地向量表246
5.3.3 APIC的工作模式和APIC ID247
5.3.4 组成Local APIC ID的处理器拓扑248
5.3.5 Local APIC的地址映射249
5.3.6 I/O APIC的地址映射250
5.3.7 多处理器的初始化过程和MP规范251
5.3.8 高级的配置和电源接口(ACPI)规范252
5.4 本章代码清单252
5.5 获取ACPI申领的物理内存地址范围271
5.5.1 ACPI的数据结构和表271
5.5.2 E820功能调用和内存地址范围结构272
5.5.3 查询和保存物理地址映射数据272
5.5.4 准备映射ACPI申领的内存274
5.5.5 映射ACPI申领的内存275
5.6 访问ACPI的数据结构和表277
5.6.1 根系统描述指针结构277
5.6.2 搜索根系统描述指针结构278
5.6.3 系统描述表的层次结构和表头格式278
5.6.4 扩展的系统描述表XSDT280
5.6.5 通过XSDT搜索多APIC描述表MADT281
5.6.6 根系统描述表RSDT282
5.6.7 通过RSDT搜索多APIC描述表MADT283
5.6.8 多APIC描述表MADT的格式284
5.6.9 准备遍历中断控制器结构列表286
5.6.10 从中断控制器结构内提取处理器和APIC信息287
5.7 映射APIC地址288
5.8 测量Local APIC定时器289
5.8.1 Local APIC定时器290
5.8.2 Local APIC定时器的精度290
5.8.3 APIC定时器的本地向量表寄存器及其设置291
5.8.4 设置CMOS RTC以测量Local APIC定时器292
5.8.5 测量Local APIC定时器在1ms内经历的时钟周期数294
5.9 使用Local APIC定时器中断切换任务295
5.9.1 多处理器系统的虚拟线模式295
5.9.2 中断输入引脚LINT0的本地向量表寄存器296
5.9.3 设置Local APIC定时器298
5.10 使用经由I/O APIC的中断执行任务切换299
5.10.1 I/O APIC概述300
5.10.2 I/O APIC的I/O重定向表寄存器302
5.10.3 用I/O APIC投递的中断实施任务切换303
5.11 逻辑目标模式下的中断目标判别机制304
5.12 APIC中断的优先级及其相关的寄存器305
5.13 APIC中断的接受机制306
5.14 大力度优惠优先级模式的中断处理307
第6章 多处理器环境下的多任务管理和调度308
6.1 本章代码清单309
6.2 高 速 缓 存338
6.3 数据竞争和锁339
6.3.1 单处理器环境下的数据竞争340
6.3.2 多处理器环境下的数据竞争342
6.3.3 原子操作343
6.3.4 锁和自旋锁345
6.3.5 分支预测和PAUSE指令347
6.3.6 多行宏定义348
6.3.7 锁在内核例程中的应用350
6.3.8 互斥锁的一般原理352
6.4 内核的初始化353
6.4.1 处理器专属存储区(每CPU数据区)354
6.4.2 为自举处理器BSP分配专属存储区355
6.4.3 处理器专属存储区的访问356
6.5 多处理器系统的初始化358
6.5.1 多处理器系统的初始化协议算法358
6.5.2 本章的多处理器多任务调度方案360
6.5.3 中断命令寄存器ICR362
6.5.4 本章的AP初始化代码简介363
6.5.5 将AP初始化代码传送到指定位置364
6.5.6 向所有应用处理器广播SIPI消息365
6.6 应用处理器AP的初始化过程366
6.6.1 进入保护模式366
6.6.2 进入64位模式367
6.6.3 为每个应用处理器创建必要的数据结构369
6.6.4 对称多处理器系统的实现370
6.6.5 用SWAPGS指令访问专属存储区371
6.6.6 开启Local APIC并进入停机待命状态373
6.7 由自举处理器BSP继续完成剩余的内核初始化工作374
6.7.1 等待所有应用处理器完成初始化374
6.7.2 创建系统外壳任务并为其指定时间片375
6.7.3 广播新任务认领消息并进入预定状态376
6.8 多处理器多任务的管理和调度377
6.8.1 新任务认领中断的处理过程377
6.8.2 在任务链表中查找就绪任务379
6.8.3 用CMPXCHG指令以无锁方式操作链表节点381
6.8.4 为新任务指定时间片382
6.8.5 恢复任务的状态并开始执行383
6.8.6 时间片到期中断的处理过程384
6.8.7 处理器专属存储区的必要性385
6.8.8 外壳任务的执行流程387
6.8.9 用户任务的执行流程388
6.8.10 任务的终止388
6.9 程序的编译和执行389
第7章 多处理器环境下的多线程管理和调度391
7.1 任务(进程)和线程391
7.2 本章代码清单392
7.3 本章的任务控制块PCB和线程控制块TCB426
7.4 任务及其主线程的创建429
7.5 线程的调度和切换431
7.5.1 新线程认领中断的处理过程431
7.5.2 查找处于就绪状态的线程432
7.5.3 恢复并执行指定的线程434
7.5.4 时间片到期中断的处理过程435
7.6 系统外壳任务及其主线程的执行436
7.7 将例程创建为线程437
7.7.1 将例程创建为线程437
7.7.2 创建线程控制块TCB和线程私有的栈438
7.7.3 例程返回和结束线程的区别439
7.7.4 如何用RET指令结束线程440
7.7.5 在栈中构造结束线程的栈帧441
7.7.6 将TCB添加到当前任务的TCB链表442
7.8 线程的执行443
7.8.1 动态内存分配444
7.8.2 在栈中保存所有缓冲区的线性地址444
7.8.3 字符串的生成、连接和打印446
7.9 线程的结束和任务的终止447
7.10 程序的编译和执行448
第8章 数据竞争和互斥锁450
8.1 本章代码清单450
8.2 线程的休眠和唤醒510
8.2.1 执行线程休眠的系统调用510
8.2.2 保存和修改休眠线程的状态512
8.2.3 安装系统管理中断514
8.2.4 系统管理中断的处理过程515
8.2.5 唤醒休眠的线程516
8.3 数据竞争的实例516
8.3.1 在两个同时执行的线程内访问共享数据517
8.3.2 线程等待519
8.3.3 唤醒处于等待状态的线程520
8.3.4 打印两个线程操作之后的共享数据520
8.3.5 并发线程的数据竞争过程522
8.4 使用锁定的原子操作解决数据竞争523
8.5 使用互斥锁解决数据竞争525
8.5.1 互斥锁的创建和初始化525
8.5.2 互斥锁的获取(加锁)525
8.5.3 唤醒等待互斥锁的线程526
8.5.4 互斥锁的释放527
8.5.5 使用互斥锁之后的运行效果527
8.6 互斥锁的应用策略528
内容摘要
传统上,大家都是在流行的操作系统(如Windows和Linux)上编写并发程序的,而且只能使用高级语言。这使得多处理器环境下的多任务和多线程调度、原子操作、锁、线程同步等内容对很多人来说是笼统的、抽象的,像隔了层纱一样,看不见本质。相反,如果用汇编语言实现一个简单的操作系统内核,并演示多处理器环境下的多任务、多线程、锁和线程同步,这是可能的吗?我相信没有人会觉得这是简单的事情。但事实上,如果你想来一个简单的,其实也很容易,这本书就能告诉你如何实现它。
本书在出版前开放了部分章节供读者阅读,也上线了配套的视频课程。
米龙评论:过去学习操作系统理论知识,诸多晦涩的概念难以理解,对于虚拟内存、分页、数据竞争、锁、原子操作等机制如同隔雾看花,不得要领。本书首次从汇编语言层面剖析了操作系统的基本原理,深入讲解了时下主流的x64多处理器架构。跟随本书章节,诸多迷雾豁然开朗。
零叶小舟评价:非常棒的内容,老师对INTEL CPU和操作系统研究得太透彻啦!这是我学过的操作系统课程中优选的,没有之一。学完之后,知其然,知其所以然。希望老师继续开课,比如ARM汇编、手写 Linux 操作系统等。
Hiodis评价视频课程:底层,核心,精简,很好,丰富,到位。
— 没有更多了 —
以下为对购买帮助不大的评价