80386保护模式下实现 Hello World

x86开机原理:从加电复位到保护模式的硬件启动全链路解析 操作系统启动过程是计算机底层技术的核心入口,其本质是CPU如何从加电复位开始,通过实模式、段式寻址、中断向量表等机制完成初始引导,并最终切换至保护模式实现内存隔离与特权分级。理解这一过程,需掌握8086分段寻址的工程妥协逻辑、CR3寄存器在页式管理中的枢纽作用,以及GDT/IDT等硬件描述符表对安全边界的硬性约束。这些机制共同构成了现代多任务系统的基础支撑,广泛应用于内核开发、驱动编写、嵌入式启动和安全研究等工程实践场景。本文聚焦x86架构下‘按下电源键’到‘Hello World刷屏’的完整物理执行路径, 阅读详情

利用选择子 拿到对应的段描述符,之后自然就可以拿到段基址,再加上段内偏移地址,就可以跳转
dword 双字 32位

在这里插入图片描述
word 两个字节 16位
dword 四个字节 32位

问题:为什么要明确的标识出 dword 32位呢?

答案:因为我们现在的无条件跳转 jmp 是从16位代码段 跳转到 32位代码段,16位代码段的意思就是 编译器在默认的情况下 对16位代码段里面的立即数 解释为16位。编译器有默认的准则,如果不明确指定,则在16位代码段中,编译器会默认 认为这个立即数就是16位的,多的部分就扔掉了。

如下代码段,在从16位代码段 跳转到 32位代码段的时候,没有明确的给编译器指定 dword !!,那么编译器就会按照16位代码段默认准则 即16位 进行编译,看到立即数,就按照16位的方式解释它,如果该立即数大过16位数据能够表示的范围,就会截断,所以这里 编译器就会认为跳转到 32位代码段 偏移地址为 0x5678的地方,1234 舍弃。

所以 dword 就是告诉编译器,现在要从16位跳转到 32位,因此解释这一行语句的时候,用 32位的方式来解释 !!!

在这里插入图片描述

显卡的主要任务是 提供要显示的数据,并且还有一个额外的智能:控制显示器的工作状态。当显卡控制完显示器,并提供好数据之后,显示器就可以把数据显示出来了。
显卡所提供的数据是放在现存中的,显存用来存储需要显示的数据。在本质上 和内存无差别,只不过显存是存在于显卡内部的。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
所以直接向这个地址范围内写数据,显存当中的内容就会发生改变,对应的屏幕当中的内容也会发生改变。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
自定义函数 需要一个栈空间,就是一段内存空间,这段内存空间在保护模式下 是需要被定义的,通过段描述符定义,所以可以在全局段描述符表中 新增一个 段描述符 ,代表全局的栈段。用于保护模式下的函数调用。

而我们需要打印的字符串可以放到 数据段,以往的学习表明 数据段就是 全局的一段数据空间,该空间存放数据,其中字符串也是放到全局数据段中的\,并且是放到全局只读数据段。 而这个所谓的全局数据段 本质就是一块内存,既然是一块内存,那就应该用段描述符定义一下,所以可以在 全局段描述符表中添加一个 段描述符,即数据段描述符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
需要注意的是:80386以及之后的处理器 的16位实模式下,是可以使用32位寄存器 32位地址的,80386以及之后的处理器 虽然上电之后处于 8086的实模式,但是这是为了兼容8086 而 故意使用的 16位运行模式,即此时 对应的 立即数 或者寄存器 都使用16位,但这是为了兼容,实际80386以及之后的处理器 的16位实模式下 是可以使用32位寄存器和地址的!!!

loader.asm

%include "inc.asm"

org 0x9000

jmp CODE16_SEGMENT

[section .gdt]
; GDT definition
;                                 段基址,       段界限,       段属性
GDT_ENTRY       :     Descriptor    0,            0,           0
CODE32_DESC     :     Descriptor    0,    Code32SegLen - 1,    DA_C + DA_32
;显存段描述符
;显存段属性:DA_DRWA + DA_32 --> 32位保护模式下的段,并且该段 可读可写 并且在这一刻之前 显存已经被访问过了(因为之前BIOS需要打印的信息 都是通过操作显存 显卡完成的)
VIDEO_DESC      :     Descriptor 0xB8000,     0x07FFF,         DA_DRWA + DA_32

;全局数据段 段描述符
;全局数据段属性 :32位保护模式下 只读段
DATA32_DESC     :     Descriptor    0,    Data32SegLen - 1,    DA_DR + DA_32

;全局栈空间 段描述符
;全局栈空间属性 :32位保护模式下 可读可写段   范围 0 - 0x7c00 定义为32位保护模式下全局栈空间
STACK_DESC      :     Descriptor    0,     TopOfStackInit,     DA_DRW + DA_32
; GDT end

GdtLen    equ   $ - GDT_ENTRY

GdtPtr:
          dw   GdtLen - 1
          dd   0
          
          
; GDT Selector

Code32Selector    equ (0x0001 << 3) + SA_TIG + SA_RPL0
;定义 显存段描述符VIDEO_DESC 的选择子,在全局段描述符表中的下标是2  所以段描述符索引值是 2
;属性是 SA_TIG(表示该选择子想要去访问的段描述符是 全局段描述符) + SA_RPL0(特权级 第0特权级)
VideoSelector     equ (0x0002 << 3) + SA_TIG + SA_RPL0

;定义 全局数据段 段描述符DATA32_DESC的 选择子,在全局段描述符表中的下标是3  所以段描述符索引值是 3
;属性是 SA_TIG(表示该选择子想要去访问的段描述符是 全局段描述符) + SA_RPL0(特权级 第0特权级)
Data32Selector    equ (0x0003 << 3) + SA_TIG + SA_RPL0

;定义 栈空间 段描述符STACK_DESC的 选择子,在全局段描述符表中的下标是4  所以段描述符索引值是 4
StackSelector     equ (0x0004 << 3) + SA_TIG + SA_RPL0

; end of [section .gdt]

; 定义常量  初始栈指针位置
TopOfStackInit    equ 0x7c00

;定义 32位保护模式 数据段,存放字符串
[section .dat]
[bits 32]
DATA32_SEGMENT:
	;定义需要打印的字符串 以0结束
    DTOS               db  "D.T.OS!", 0
	;字符串的长度,此时代表字符串的 段内偏移地址
    DTOS_OFFSET        equ DTOS - $$
    HELLO_WORLD        db  "Hello World!", 0
    HELLO_WORLD_OFFSET equ HELLO_WORLD - $$

;数据段长度 
Data32SegLen equ $ - DATA32_SEGMENT

[section .s16]
[bits 16]
CODE16_SEGMENT:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
	;在16位 代码段中 设置了栈指针
    mov sp, TopOfStackInit
    
; initialize GDT for 32 bits code segment
;设置 CODE32_SEGMENT段 32位段基址 到  对应的段描述符对应位置
    mov esi, CODE32_SEGMENT
    mov edi, CODE32_DESC
    
    call InitDescItem
    
;设置 数据段 32位段基址 到  数据段 段描述符对应位置
    mov esi, DATA32_SEGMENT
    mov edi, DATA32_DESC
    
    call InitDescItem
    
    ; initialize GDT pointer struct
    mov eax, 0
    mov ax, ds
    shl eax, 4
    add eax, GDT_ENTRY
    mov dword [GdtPtr + 2], eax

    ; 1. load GDT
    lgdt [GdtPtr]
    
    ; 2. close interrupt
    cli 
    
    ; 3. open A20
    in al, 0x92
    or al, 00000010b
    out 0x92, al
    
    ; 4. enter protect mode
    mov eax, cr0
    or eax, 0x01
    mov cr0, eax
    
    ; 5. jump to 32 bits code
    jmp dword Code32Selector : 0

;初始化段描述符中的 段基址, 根据代码段标签初始化对应的段描述符
; esi    --> code segment label  代码段标签
; edi    --> descriptor label 段描述符标签
InitDescItem:
;备份 eax
    push eax

	; 设置32位段基址 到 段描述符对应位置
    mov eax, 0
    mov ax, cs
	;eax 左移4位
    shl eax, 4
	;代码段标签
	;段寄存器<<4) + (32位代码段 偏移地址   == 32位代码段的真实物理地址,即段基地址
    add eax, esi
	;将 ax寄存器保存的值 放到 段描述符标签+2 地址处, 段基址的0-15位 放到 段描述符的16-31 位
    mov word [edi + 2], ax
	;eax 右移16位  也就是低16位被移出去了
    shr eax, 16
	; al(ax低8位)   此时al是32位代码段基地址当中的第三个字节(段基址 16-23位) 放到 段描述符的32-39位
    mov byte [edi + 4], al
	; ah(ax高8位)    此时ah是32位代码段基地址当中第四个字节(段基址 24-31位) 放到 段描述符的55-63位 第七个字节
    mov byte [edi + 7], ah
   
;回复 eax   
    pop eax
    
    ret
    
    
[section .s32]
[bits 32]
CODE32_SEGMENT:
;首先分别将 
	;显存段 基地址放到 gs段寄存器中,gs段寄存器用于存放 显存段基地址
	;栈空间段 基地址放到 ss段寄存器中,ss段寄存器用于存放 栈空间段基地址
	;数据空间段 基地址放到 ds段寄存器中,ds段寄存器用于存放 数据段基地址

; 将显存段描述符的选择子 放到 gs寄存器中,所以此时gs寄存器就代表了这整个显存段
    mov ax, VideoSelector
    mov gs, ax
   
	;通过栈空间段描述符的选择子 获取段的起始地址 设置到 ss
    mov ax, StackSelector
    mov ss, ax
 
;通过段描述符的选择子 获取段的起始地址 即ds
;再通过具体的段内偏移地址ebp , 得到具体地址  ds:ebp
	;通过段描述符的选择子 设置 对应段寄存器,即获取数据段 段地址
    mov ax, Data32Selector
    mov ds, ax
    
	;获取目标字符串在段内偏移地址, 因为是保护模式下的编程,地址用段内偏移地址
    mov ebp, DTOS_OFFSET
	;打印属性 黑底红字
    mov bx, 0x0C
	;打印位置
    mov dh, 12
    mov dl, 33
    
    call PrintString
    
    mov ebp, HELLO_WORLD_OFFSET
    mov bx, 0x0C
    mov dh, 13
    mov dl, 31
    
    call PrintString
    
    jmp $

; 32位保护模式下下的 打印函数 需要定义在 [section .s32] 代码节下
; ds:ebp    --> string address  目标字符串地址
; bx        --> attribute  打印属性
; dx        --> dh : row, dl : col  打印坐标
PrintString:
    push ebp
    push eax
    push edi
    push cx
    push dx


print:
	;取当前字符
    mov cl, [ds:ebp]
	;判断当前字符是否为0
    cmp cl, 0
	;如果是0 则打印结束  跳转到 end标签
    je end
	;如果不为0 
	; 行*80,相乘结果放到 eax寄存器中
    mov eax, 80
    mul dh
	
	;加列坐标 dl  -->  eax+列
    add al, dl
	; eax*2  得到最终的打印位置
    shl eax, 1
	;将打印位置 放到 edi 中
    mov edi, eax
	;获取字符属性 - 高八位  需要显示字符的颜色
    mov ah, bl
	;获取字符属性 - 低八位  需要显示的字符 
    mov al, cl
	;将字符写入显存中 打印
    mov [gs:edi], ax
	;下一个字符
    inc ebp
	;下一个字符打印的位置
    inc dl
	;无条件跳转 循环
    jmp print

end:
    pop dx
    pop cx
    pop edi
    pop eax
    pop ebp
    
    ret
    
Code32SegLen    equ    $ - CODE32_SEGMENT
OS Labs Review 声明:本blog基于2019 NJU OS Labs Lab1 系统引导 1、任务 通过 start.s 从实模式切换到保护模式,进入 boot.c 中调用 app 完成 hello world 的打印 2、细节 …… cli #clearinteruption 关闭中断是为了保证 cpu 在开启 A20 地址线时不被外部中断打扰 inb $0x92, %al #Fast set up A20 Line with port 0x92,necessary or not? …… 必须要打开 A20 地址 阅读详情

相关推荐

用C语言在NDS上编写程序

在DS上进行开发是我一直的梦想,虽然有DSBasic, DSLua等解释器,但是总感觉很别扭,而且没有更多的语言支持。昨天偶然发现了一个DS上的x86虚拟机,我想在这上面测试一下。 我们需要以下组件: **DSx86** 在DS上模拟x86环境的虚拟机 地址:http://dsx86.patrickaalto.com/,目前最新版本0.14Beta 需要的文件有: DSx86.

u013890660的专栏 2006

动手写操作系统4----实现保护模式

这里实现引导区和内核区分离以及保护模式功能。 1.引导区和内核区分离实现 前面实现制作虚拟软盘,引导扇区写入代码来实现helloworld,系统启动来加载软盘的引导扇区即第一个扇区,由于第一个扇区只有512Byte,而操作系统内核必定大于512B,因此一般都将引导扇区作为内核加载器来使用,将操作系统代码放置于软盘的后续扇区中,当系统启动时,首先加载引导扇区,由引导扇...

大魔王 902

VirtualBox搭建FreeDOS+DJGPP复古开发环境:安装配置与避坑指南

在虚拟机中还原老式DOS开发环境,是研究早期C语言编程与底层系统原理的实用路径。DOS系统虽然诞生已久,但其命令行工具链与编译机制对理解现代软件开发仍有不可替代的启发价值。DJGPP作为GCC在DOS平台的移植版本,通过DPMI协议突破640KB内存限制,让32位保护模式程序在精简环境下稳定运行,这一设计思想也深刻影响了后续嵌入式与操作系统教学。借助VirtualBox的IDE控制器配置与FreeDOS的开源特性,无需实体老机器即可复现上世纪程序员的工作流。该方案适合运行老代码、学习汇编与C语言混合编程、演

weixin_31364787的博客 286

保护模式下编程

;1. ;=========================================================== ;在保护模式下32位CPU仍然可以用20位地址来实现32位地址线寻址 ;16位CPU: 16位段寄存器+16位偏移地址 (经地址加法器) -> 20位物理内存地址 ;32位CPU: 32位地址的内存段信息存入在一张内存表中,只需将表的索引存入16寄存器当中即可 ;保存表中索引的段寄存器称为:段选择子 ;表中每个表示32位内存段信息称为:段描述符(保存了段的地址和段的长

维唯为为_优快云博客 707

DJGPP 2.04:DOS下32位开发套件的环境搭建与内存模型实战

在操作系统底层开发与逆向工程领域,理解CPU实模式与保护模式的内存管理差异,是掌握嵌入式或遗留系统编程的关键。保护模式通过分段和分页机制为32位程序提供平坦地址空间,而DPMI(DOS保护模式接口)则是DOS环境下进入该模式的桥梁。当开发者需要在16位DOS系统中编译运行现代C/C++代码时,DJGPP作为一套完整的32位工具链,集成了GCC、标准库与GDB调试器。它借助DPMI将80386以上CPU切换为32位平坦内存模型,使DOS突破传统16位限制,适用于维护老旧业务系统、操作系统课程设计及研究底层中断

weixin_33417488的博客 189

第一个汇编程序-Hello World

第一个汇编程序-Hello World 调用MessageBoxA弹出对话框

编写最简单的内核:HelloWorld

内核是操作系统最核心的内容,主要提供硬件抽象层、磁盘及文件系统控制、多任务等功能,由于其涉及非常广泛的计算机知识,很少被人们所熟悉,因而披上了一层神秘的面纱。 本文将从零开始实现一个最简单的内核,其可以通过x86系统的GRUB引导启动,并向屏幕输出“Hello World!“字符串。该内核代码非常简短,并且在本人的Debian 7系统中可以正常运行。 x86机器启动过程 在具体实

萌萌的It人 www.itmmd.com 1702

80386保护模式编程

80386保护模式编程.pdf 希望能帮助有需要的人

汇编系列03-不借助操作系统输出Hello World

通过将汇编程序作为主引导扇区的内容,从而绕过操作系统,在屏幕上打印Hello, world。有助于理解计算机的工作方式。

码农无双的博客 1188

保护模式下的80386及其编程 扫描版 pdf

保护模式下的80386及其编程 pdf,扫描版的

LTspice introduction - 2 LTspice的界面

LTspice的界面主要有两个:Schematic Capture和Waveform Viewer Schematic Capture 它主要是用来画电路图的,画完电路图之后,添加一些dot 命令同时选择一些仿真的参数,点击执行(Run)Waveform Viewer 如果你的仿真不是op point的话,一个都会打开它,在它里面你可以画图相应的图形。 有两种方式可以在Viewer

贾亮的专栏 3221

【汇编语言程序设计 张悠慧老师】80X86计算机组织结构简述

目录 1.计算机系统 1.1总体概括(现细节已有改变) 1.2玩具程序helloworld的执行步骤 1.2.1 将程序从磁盘装载到内存中 1.2.2 CPU将指令逐条读入,一遍读取一遍执行 1.2.3.CPU对显卡进行操作然后输出 2.存储器主存 3.80X86处理器与保护模式 3.1 8086/8088 3.2 80186/80286 3.3 80386 3.3.1 简介 3.3.2三种工作模式 3.3.3 保护模式下的80X86 3.3.4 内存地址的组成 3.3.5.

Edidaughter的博客 500

WSL2部署Cadence Virtuoso IC25.1:Ubuntu 26.04排障实录

WSL2以轻量虚拟机结合完整Linux内核,为Windows桌面环境提供了原生级Linux运行能力,解决了传统虚拟机资源开销大、双系统切换低效的问题。对于依赖X11图形协议、FlexNet许可服务和特定动态库的EDA工具链而言,利用WSL2部署Linux发行版需要关注系统集成、显示通路与许可连通性。从技术原理看,图形层X Server的配置、动态库依赖的补齐以及license服务的主机名解析,共同构成EDA工具在WSL2中稳定运行的关键环节。在芯片设计场景中,设计工程师常需在Windows办公机与Linux

weixin_29597551的博客 211

在Visual Studio 2022中配置与开发32位Intel汇编程序

汇编语言作为最接近硬件的编程语言,其核心价值在于对计算机底层资源的直接控制与极致性能优化。其工作原理是通过操作码直接指挥CPU的寄存器、内存和运算单元,绕过高级语言编译器的抽象层,实现对指令周期和内存布局的精确掌控。这种技术价值在需要极致性能、直接硬件操作或进行底层系统研究的场景中无可替代,例如嵌入式系统驱动开发、操作系统内核、实时音视频处理核心算法以及软件安全分析等领域。本文聚焦于如何在现代集成开发环境Visual Studio 2022中,搭建完整的32位Intel汇编开发工作流,涵盖从环境配置、项目创

weixin_33951761的博客 503

【YOLOv7-环境搭建】PyTorch安装后输出版本显示No module named ‘Torch’的解决方法

【YOLOv7-环境搭建】PyTorch安装后输出版本显示No module named ‘Torch’的解决方法:①检查PyCharm导入的环境是否错误②添加Torch包

qq_59942266的博客 4970

Windows 11/10系统盘被BitLocker锁了别慌!手把手教你用manage-bde命令找回密钥并解锁

本文详细介绍了当Windows 11/10系统盘被BitLocker锁定后的恢复方法,重点讲解了如何使用manage-bde命令行工具找回密钥并解锁加密驱动器。通过进入Windows恢复环境、诊断锁定状态、提取恢复密钥ID以及执行解锁操作等步骤,帮助用户有效解决BitLocker锁定问题,同时提供了后续防护优化建议和高级故障排除技巧。

weixin_42542669的博客 1462

在Visual Studio 2022中搭建32位Intel汇编开发环境与调试实战

汇编语言作为直接与CPU对话的低级编程语言,是理解计算机体系结构、操作系统原理及进行系统级编程和性能优化的基石。其核心在于将人类可读的指令助记符转换为机器码,从而精确控制处理器、寄存器和内存。掌握汇编对于深入理解程序执行机制、进行逆向工程和底层性能调优具有不可替代的技术价值。在嵌入式系统、操作系统内核、驱动开发及对执行效率有极致要求的场景中,汇编依然发挥着关键作用。本文聚焦于如何在现代集成开发环境Visual Studio 2022中,配置并高效开发32位Intel风格汇编程序,充分利用其智能感知和一体化调

weixin_33693070的博客 367

YOLOv11改进策略【注意力机制篇】| 2024 蒙特卡罗注意力(MCAttn)模块,提高小目标的关注度

本文记录的是基于蒙特卡罗注意力(MCAttn)模块的YOLOv11目标检测改进方法研究。利用提高的跨尺度特征提取能力,使模型能够更好地传递和融合提取的多尺度特征,提高对小目标的关注度。Exploiting Scale-Variant Attention for Segmenting Small Medical Objects使用一种基于随机采样的池化操作来生成尺度无关的注意力图。它从三个不同尺度(3×33×33×3、2×22×22×2和1×11×11×1,即池化张量)中随机选择一个1×11×11×1注意力图

Limiiiing的博客 3600

8086处理器架构详解:从寄存器内存分段到x86基因传承

在计算机体系结构中,CPU的指令集与寻址模式决定了软件与硬件的交互方式。x86架构作为工业界应用最广泛的指令集体系,其设计根源可追溯至1978年的8086处理器。理解寄存器分组、内存分段机制以及物理地址的计算原理,是掌握汇编语言与底层系统开发的基础。8086通过段寄存器与偏移地址组合实现20位寻址,解决了16位寄存器访问1MB内存空间的工程难题。这一设计不仅影响了后续x86系列对兼容性的持续坚持,也为现代操作系统的内存管理提供了历史参照。无论是从事驱动开发、逆向工程还是编译器设计,深入理解实模式下的执行流程

weixin_34009794的博客 260

【软考之软件设计师】学习笔记

interface 接口implements 实现接口(与接口配套使用)接口里要是有方法定义,子类就会实现。

云轩阁 2533

YOLOv12涨点改进 | 全网首发,Conv改进篇 | CVPR 2025 | YOLOv12引入FDConv频率动态卷积,含A2C2f_FDConv二次创新模块,能够捕捉更加丰富和复杂的特征信息

本文提出了一种改进YOLOv12目标检测模型的方法——频率动态卷积(FDConv)。FDConv通过增强卷积核的频率响应多样性,使模型能够更好地处理不同频率信息,从而提高检测精度。该方法包含三个关键组件:傅里叶离散权重(FDW)实现频率分组,核空间调制(KSM)动态调整频率响应,以及频率带调制(FBM)进行频域调节。实验结果表明,FDConv能以较少的参数增长(仅增加3.6M)显著提升模型性能,在目标检测、实例分割等任务中优于传统动态卷积方法。该方法可灵活集成到ResNet、ConvNeXt等多种架构中。

Ai缝合怪、助力小伙伴高效发论文 421

汇编语言编写的Hello World

Linux 下用汇编语言编写的代码具有两种不同的形式。第一种是完全的汇编代码,指的是整个程序全部用汇编语言编写。尽管是完全的汇编代码,Linux 平台下的汇编工具也吸收了 C 语言的长处,使得程序员可以使用 #include、#ifdef 等预处理指令,并能够通过宏定义来简化代码。第二种是内嵌的汇编代码,指的是可以嵌入到C语言程序中的汇编代码片段。虽然 ANSI 的 C 语言标准中没有关于内嵌汇编代

后花园 2万+

171、运动控制中的标定:摩擦力与死区补偿标定

摘要(149字) 运动控制系统中的摩擦力与死区补偿是提升精度的关键。摩擦力分为静摩擦、库仑摩擦和粘滞摩擦,其中Stribeck效应是低速抖动的主因;死区则表现为控制信号的无效区间。有效标定方法包括恒速测试(摩擦力)和斜坡响应法(死区)。补偿策略需采用分段前馈和动态调整,避免过度补偿导致振荡。实践中要注意机械状态检查、补偿量限幅,并定期重新标定。硬件升级配合算法补偿才能实现最优控制,标定工作应优先于PID参数调整。

m0_50546716的博客 231

操作系统

操作系统 操作系统运行程序 hello world程序的执行过程 用户通知操作系统执行hello world应用程序 操作系统找到hello world程序的相关信息, 程序的相关信息(ELF文件信息, 不包括.text, .data, .bss, stack segment, heap segment, 但是ELF信息包含了他们的位置)包含了许多的信息, 比如是否是可执行文件, 还可...

anmin1992的专栏 118

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

上一篇: 80286 与 80386,实模式与保护模式切换编程
下一篇: 从保护模式返回实模式
Ma浩然
博客等级 码龄9年 1万+粉丝 462原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ma浩然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值