局部段描述符表的使用

简介: 局部段描述符表的使用

局部段描述符表基本概念

  • 描述符表有 GDT 和 LDT 两种,在保护模式的代码实现中我们用的都是 GDT
  • 现在我们就来学习一下 LDT
  • LDT 全称: Local Descripter table
  • 同 GDT 一样,LDT 本质上也是段描述符表,可以看成段描述符数组
  • 也是通过选择子的方式来访问局部段描述符表中的元素
  • 局部段描述符和选择子与全局段描述符和选择子格式一致

LDT 与 GDT 使用的差异

  • 局部段描述符表从第 0 项开始使用,而全局段描述符表是从第 1 项开始使用
  • 加载局部段描述符表使用的是 lldt 指令,而加载全局段描述符表使用的是 lgdt 指令
  • 局部段描述符表需要在全局段描述符表中注册(增加描述项)

LDT 的意义

  • 它是 CPU 厂商为在硬件一级原生支持多任务而创造的表,按照 CPU 的设想,一个任务对应一个 LDT
  • CPU 厂商建议每个任务的私有内存段都应该放到自己的段描述符表中,该表就是 LDT
  • LDT 是实现多任务的基本要素
  • 当然,现在可能很难理解 LDT 对多任务的意义,可以暂时先放着,心中有个概念就行,后面再逐步具体体会

LDT 的定义与使用

  • 先上完整代码:loader.asm
  • 参考 GDT 的实现,LDT 实现与 GDT 非常相似
  • 首先是局部段描述符表和局部段选择符的定义
; Task A 局部段描述符表定义,段基址先默认为 0 ,后面填充
TASK_A_LDT_BASE     :
TASK_A_CODE32_DESC  : Descriptor 0, TASK_A_CODE32_SEG_LEN - 1,  DA_C + DA_32
TASK_A_DATA32_DESC  : Descriptor 0, TASK_A_DATA32_SEG_LEN - 1,  DA_DR + DA_32
TASK_A_STACK32_DESC : Descriptor 0, TASK_A_STACK32_SEG_LEN - 1, DA_DRW + DA_32
; ...
TASK_A_LDT_LEN      equ   $ - TASK_A_LDT_BASE  ; 长度 = 当前地址 - TASK_A_LDT_BASE 地址
; Task A 局部段选择符定义,RPL = 0; TI = 1
TASK_A_CODE32_SELECTOR    equ   (0x0000 << 3) + SA_RPL0 + SA_TIL
TASK_A_DATA32_SELECTOR    equ   (0x0001 << 3) + SA_RPL0 + SA_TIL
TASK_A_STACK32_SELECTOR   equ   (0x0002 << 3) + SA_RPL0 + SA_TIL
  • 注意 lldt 指令加载的是选择子,与 lgdt 不同
mov ax, TASK_A_LDT_SELECTOR
lldt ax
  • 别忘了段基址需要填充
CODE16_START
  ...
  mov esi, TASK_A_LDT_BASE
  mov edi, TASK_A_LDT_DESC 
  call InitDescItem
  mov esi, TASK_A_CODE32_SEGMENT
  mov edi, TASK_A_CODE32_DESC
  call InitDescItem
  mov esi, TASK_A_DATA32_SEGMENT
  mov edi, TASK_A_DATA32_DESC
  call InitDescItem
  mov esi, TASK_A_STACK32_SEGMENT
  mov edi, TASK_A_STACK32_DESC 
  call InitDescItem
  • 注意,局部段描述符表需要在全局段描述符表中注册(增加描述项),即把局部段描述符表当做一个段,然后给这个段定义一个全局描述符和选择符
; 全局描述符表定义
...
TASK_A_LDT_DESC : Descriptor 0, TASK_A_LDT_LEN-1, DA_LDT
; 全局段选择符定义,RPL = 0; TI = 0
...
TASK_A_LDT_SELECTOR equ (0x0005 << 3) + SA_RPL0 + SA_TIG
  • Task A 的数据段,代码段,栈段实现主体自己查看源码分析。
  • 在原 32 位代码段程序后面添加加载局部段描述符表和跳转到局部代码段执行的代码
mov ax, TASK_A_LDT_SELECTOR
lldt ax
jmp TASK_A_CODE32_SELECTOR:0
  • 于是,程序跳转到 TASK_A_CODE32_SEGMENT 代码处执行
  • TASK_A_CODE32_SEGMENT 处的程序即为局部代码段,实现功能:打印 “Task A” 字符串
  • 注意了:为啥又重新实现了打印函数 TaskAPrintString ,这个函数不是跟 print_str_32 一模一样的吗?
  • 因为 TaskAPrintString 和 print_str_32 不属于同一个代码段,段界限规定了每个程序段的范围,A 程序当然无法调用 B 程序中的代码。这正体现了保护模式的保护二字
  • 最后看一下代码的运行效果

  • 问题:TaskAPrintString 和 print_str_32 实现的功能一模一样,那么,如何实现一个函数,可供不同的代码段调用呢?
  • 请看下一章节讲解
目录
相关文章
|
移动开发 前端开发 API
深入理解前端路由:构建现代 Web 应用的基石(上)
深入理解前端路由:构建现代 Web 应用的基石(上)
深入理解前端路由:构建现代 Web 应用的基石(上)
|
Ubuntu
Ubuntu的中文乱码问题
Ubuntu的中文乱码问题
1162 2
|
API 数据库 流计算
有大佬知道在使用flink cdc实现数据同步,如何实现如果服务停止了对数据源表的某个数据进行删除操作,重启服务之后目标表能进行对源表删除的数据进行删除吗?
【2月更文挑战第27天】有大佬知道在使用flink cdc实现数据同步,如何实现如果服务停止了对数据源表的某个数据进行删除操作,重启服务之后目标表能进行对源表删除的数据进行删除吗?
335 3
|
BI
宜搭流程表单报表的表格内如何设置点击跳转到表单的详情页面
宜搭流程表单报表的表格内如何设置点击跳转到表单的详情页面
1325 0
|
机器学习/深度学习 人工智能 自然语言处理
《C++与AMD ROCm:人工智能计算的强力引擎》
AMD ROCm平台是一个开放的、基于GPU的高性能计算平台,为人工智能计算提供卓越加速能力。结合C++这一高效编程语言,ROCm平台在深度学习、计算机视觉和自然语言处理等领域展现出巨大潜力。C++对底层硬件的精细控制与庞大的生态系统,使其在ROCm平台上实现更低延迟和更高吞吐量,适用于实时性要求高的任务。尽管面临编程复杂性和兼容性挑战,通过持续优化和技术支持,ROCm与C++的组合将在更多领域推动人工智能技术的实际应用,助力构建智能世界。
378 18
|
安全 物联网 物联网安全
智能物联网安全:物联网设备的防护策略与最佳实践
【10月更文挑战第27天】随着物联网技术的快速发展,智能设备已广泛应用于生活和工业领域。然而,物联网设备的安全问题日益凸显,主要威胁包括中间人攻击、DDoS攻击和恶意软件植入。本文探讨了物联网设备的安全防护策略和最佳实践,包括设备认证和加密、定期更新、网络隔离以及安全标准的制定与实施,旨在确保设备安全和数据保护。
694 0
|
存储 中间件 数据库连接
|
Java 应用服务中间件
Process exited with an error: 1 (Exit value: 1) 问题处理
本文介绍了在本地启动项目时遇到“Process exited with an error: 1”错误的解决过程。作者首先排除了配置文件修改的影响,通过分析错误信息,推测为端口占用问题,并使用 `netstat -ano` 命令检查端口占用情况,最终通过终止占用端口的进程解决了问题。
|
JavaScript
新年倒计时动画网页特效源码
新年倒计时动画网页特效源码是一段基于JS实现的中国节日元旦2025年倒计时动画效果代码,利用此代码,可以实现任意节日的倒计时效果,欢迎对此代码感兴趣的朋友前来下载参考。
329 6
|
运维 Kubernetes Docker
深入理解容器化技术及其在微服务架构中的应用
深入理解容器化技术及其在微服务架构中的应用
963 1

热门文章

最新文章