|
cxdzxc
新手上路

积分 10
发帖 4
注册 2010-6-13
状态 离线
|
『楼 主』:
重要发现,纯DOS下,直接寻址4G
[已使用 LLM 解释]
重要发现,纯DOS下,不操作CR0,不装载描述符,直接寻址4G,欢迎验证
romdizhi equ 0fffffff0h
mov esi,romdizhi
huancun equ 80000h
qushu:
xor ax,ax
mov ds,ax
mov es,ax
mov edi,huancun
mov ecx,10h/4
db 67h ;就是这句,非常关键
rep movsd
mov ax,huancun/10h
mov ds,ax
mov es,ax
Last edited by cxdzxc on 2010-6-14 at 10:09 ]
Important discovery, in pure DOS, without operating CR0, without loading descriptors, directly addressing 4G, welcome to verify
romdizhi equ 0fffffff0h
mov esi,romdizhi
huancun equ 80000h
qushu:
xor ax,ax
mov ds,ax
mov es,ax
mov edi,huancun
mov ecx,10h/4
db 67h ; this sentence is very critical
rep movsd
mov ax,huancun/10h
mov ds,ax
mov es,ax
Last edited by cxdzxc on 2010-6-14 at 10:09 ]
LLM 解释
技术解释与背景补充
你提到的“纯DOS实模式下直接寻址4G”现象,本质是实模式下误用保护模式段描述符的非标准行为,而非实模式本身支持32位寻址。以下是关键机制与限制:
1. 核心原理:实模式下残留的保护模式段描述符
x86 CPU的段寄存器(如ds/es)在实模式下仍会保留保护模式段描述符缓存(Descriptor Cache)。若BIOS在启动过程中曾进入保护模式(如初始化硬件时),且切回实模式时未清除ds/es的描述符缓存,这些段寄存器可能仍持有32位可读/写的段描述符(基地址为0、限长为4GB)。此时,若通过67h前缀(32位寻址前缀)强制使用32位地址计算(如esi/edi),CPU会直接使用描述符缓存中的32位段信息,绕过实模式的段基址=段值×16规则,从而访问0~4GB的物理内存。
2. 关键限制与环境依赖
-
BIOS残留描述符是前提:该行为仅在BIOS切回实模式时未清除
ds/es描述符缓存的机器上有效。若手动进入保护模式并重置ds/es为无效描述符(如你后续实验代码所示),则会因描述符无效导致崩溃。
-
67h前缀的作用:仅对支持32位寻址的指令(如movsd)生效,强制使用32位地址寄存器(esi/edi)和32位地址计算,而非实模式默认的16位si/di。
-
A20地址线必须开启:若A20未开启,物理地址会在1MB处回绕(
FFFF:FFFF等价于000F:000F),无法访问1MB以上内存。开启A20需通过键盘控制器(KBC)或端口92h(依主板设计而定,如netwinxp和johnsonlam讨论的兼容性问题)。
3. 历史误解与局限性
-
并非实模式原生支持:实模式的设计上限是1MB寻址(
段值×16 + 偏移,最大FFFF:FFFF=10FFEFh),该现象是利用了CPU硬件的“遗留状态”,属于未定义行为。
-
无内存管理:直接访问4GB内存时,无法感知内存是否已被占用(如BIOS、扩展内存管理器XMS/EMS),可能导致数据覆盖或系统崩溃。规范的扩展内存访问应通过
INT 15h(XMS)、DPMI或EMS。
4. 后续讨论的补充验证
cnzdgs指出“BIOS残留描述符”的核心原因,你的实验代码也验证了这一点;netwinxp补充了A20地址线的必要性及兼容性问题,均准确解释了该现象的本质与限制。
结论
该方法是利用CPU硬件遗留状态的非标准技巧,依赖特定BIOS环境,并非实模式的原生功能。实际开发中应优先使用规范的内存管理接口,避免依赖此类未定义行为。
|
|
2010-6-14 10:06 |
|
|
cxdzxc
新手上路

积分 10
发帖 4
注册 2010-6-13
状态 离线
|
|
2010-6-14 11:01 |
|
|
cxdzxc
新手上路

积分 10
发帖 4
注册 2010-6-13
状态 离线
|
『第 3 楼』:
[已使用 LLM 解释]
cnzdgs
(满天星\n技术问题请勿私聊)
等 级:
2
更多勋章
#40楼 得分:0回复于:2010-06-15 01:54:48
16位代码中加上67H前缀就表示使用32位寻址,在实模式下也可以使用32位寻址,但要求相关段寄存器必须已装入适当的描述符,貌似还要求段寄存器的当前值必须为0(这点未验证过)。
在Windows的虚拟DOS环境中不允许使用32位寻址;在虚拟机中则要依赖于“虚拟”的具体实现,能否运行未知。在某些实体机纯DOS环境中可以运行,是由于启动时BIOS程序曾切入过保护模式,并且在ds、es中装入了32位段描述符,而在切回实模式时没有清除,所以在实模式中仍可使用。可以做个简单的验证,自己写一小段程序,切入保护模式,将ds、es装入空描述符,然后再切回实模式,之后再运行这段程序就会出问题了。
cnzdgs
(Full Star\nTechnical questions, please do not private message)
Level:
2
More badges
#40樓 Score: 0 Posted on: 2010-06-15 01:54:48
Adding the prefix 67H to a 16-bit code means using 32-bit addressing. In real mode, 32-bit addressing can also be used, but it requires that the relevant segment registers have been loaded with appropriate descriptors, and it seems that the current value of the segment register must be 0 (this has not been verified).
In Windows' virtual DOS environment, 32-bit addressing is not allowed; in a virtual machine, it depends on the specific implementation of "virtualization", and it is unknown whether it can run. In some physical machine pure DOS environments, it can run because the BIOS program entered protected mode during startup, and loaded 32-bit segment descriptors into ds and es, and did not clear them when switching back to real mode, so 32-bit addressing can still be used in real mode. You can do a simple verification: write a short program yourself, enter protected mode, load ds and es with empty descriptors, then switch back to real mode, and then running this program will have problems.
LLM 解释
技术解释与补充说明
该回复对 实模式下 32 位寻址的依赖条件 分析准确,以下是关键补充与背景说明:
1. 实模式下 32 位寻址的核心前提
实模式本身仅支持 20 位物理地址(由段基址左移 4 位 + 16 位偏移计算),但 80386 及后续 CPU 允许在实模式中通过 67h 地址大小前缀,将偏移量扩展为 32 位。此时地址计算逻辑变为:
- 段基址:仍由段寄存器值左移 4 位(16 位段机制不变)。
- 偏移量:使用 32 位寄存器(如
esi/edi)或 32 位立即数。
- 物理地址:
段基址(16位左移4) + 32位偏移,但受限于实模式的 20 位地址总线(早期 CPU)或 CPU 对实模式的硬件限制,实际访问范围仍可能被截断为 20 位(即 物理地址 & 0xFFFFF)。
然而,该特性需要段描述符高速缓存(Segment Descriptor Cache)的支持:
- 段寄存器(如
ds/es)对应的描述符高速缓存中,必须包含 32 位段大小(Limit = 0xFFFFFFFF) 的信息,否则 CPU 会因“段越界”触发异常。
- 早期 BIOS 在启动时(如初始化内存、检测硬件)会短暂进入保护模式,此时会为
ds/es 加载包含 32 位段大小的描述符;切回实模式时,BIOS 不会主动清除描述符高速缓存(因实模式本身不使用描述符),因此这些段寄存器的高速缓存仍保留 32 位属性,这是实模式下能使用 32 位寻址的关键原因。
2. 回复中验证方法的合理性
若手动切入保护模式,为 ds/es 加载 空描述符(如 Limit = 0),再切回实模式:
- 段描述符高速缓存会被更新为空描述符的属性(段大小极小),此时使用
67h 前缀访问 32 位偏移会立即触发段越界异常(#GP),验证了“依赖 BIOS 残留描述符”的结论。
3. 当年常见的误解背景
- 早期 DOS 用户对“实模式 vs 保护模式”的段机制理解不深入,容易将“BIOS 残留的描述符属性”误认为是实模式本身的特性,因此会觉得“实模式能直接寻址 4G”是“新发现”。
-
67h 前缀仅影响偏移量的位数,不改变段基址的计算方式,因此即使使用 32 位偏移,若段基址非 0,实际访问的物理地址仍可能远小于 4G(如段基址为 0x1000 时,最大物理地址为 0x10000 + 0xFFFFFFFF = 0x1000FFFF,仅 1MB 多)。
4. 兼容性限制
-
Windows VDM:虚拟 DOS 环境会严格模拟实模式的 16 位限制,主动清除段描述符高速缓存的 32 位属性,因此无法使用该特性。
-
虚拟机:依赖虚拟机对实模式的模拟精度,部分虚拟机(如早期 VMware)会完全模拟 BIOS 的描述符残留行为,而部分轻量模拟器(如 DOSBox)可能直接禁用实模式 32 位寻址。
综上,“纯 DOS 下直接寻址 4G”的本质是 利用 BIOS 残留的段描述符高速缓存,在实模式中通过 32 位偏移扩展访问范围,而非实模式本身支持 32 位物理地址。该回复的验证方法(手动修改描述符)准确且具有说服力。
|
|
2010-6-15 10:08 |
|
|
cxdzxc
新手上路

积分 10
发帖 4
注册 2010-6-13
状态 离线
|
『第 4 楼』:
使用 LLM 解释/回答一下
cxdzxc
等 级:
#42楼 得分:0回复于:2010-06-15 09:30:51
经过实验,王老师和DelphiGuy说的是正确的,应该是我的BIOS---在ds、es中装入了32位段描述符,而在切回实模式时没有清除,所以在实模式中仍可使用
下面帖出实验代码:
org 100h
cli
xor eax,eax
mov ax,cs
shl eax,4
add [gdtzhizhen+2],eax
lgdt [gdtzhizhen]
mov eax,cr0
or al,1
mov cr0,eax
mov bx,gdt1-gdt0
mov ds,bx
mov es,bx
and al,0feh
mov cr0,eax
mov ah,4ch
int 21h
gdt0 dd 0,0
gdt1 db 0ffh,0ffh,0,0,0,92h,0fh,0
gdtzhizhen dw $-gdt0,gdt0,0
----------------------------
用NASM编译成一个COM文件,先在DOS下运行这个文件,然后DEBUG 装入先前的实验代码,G命令运行就会死机了
Level:
#42nd floor Score: 0 Posted on: 2010-06-15 09:30:51
After experimentation, what Teacher Wang and DelphiGuy said is correct. It should be my BIOS---I loaded 32-bit segment descriptors in ds and es, but did not clear them when switching back to real mode, so they can still be used in real mode
The experimental code is posted below:
org 100h
cli
xor eax,eax
mov ax,cs
shl eax,4
add ,eax
lgdt
mov eax,cr0
or al,1
mov cr0,eax
mov bx,gdt1-gdt0
mov ds,bx
mov es,bx
and al,0feh
mov cr0,eax
mov ah,4ch
int 21h
gdt0 dd 0,0
gdt1 db 0ffh,0ffh,0,0,0,92h,0fh,0
gdtzhizhen dw $-gdt0,gdt0,0
----------------------------
Compile it into a COM file with NASM, run this file under DOS first, then load the previous experimental code with DEBUG, and run it with the G command will crash
|
|
2010-6-15 10:09 |
|
|
netwinxp
高级用户
   
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第 5 楼』:
使用 LLM 解释/回答一下
DOS下访问4G要先打开A20,否则访问偶数地址会出问题。
To access 4G under DOS, you need to enable A20 first; otherwise, there will be issues when accessing even addresses.
|
|
2010-6-17 20:50 |
|
|
AlexZhang
系统支持
            
积分 995
发帖 427
注册 2007-2-8
状态 在线
|
『第 6 楼』:
使用 LLM 解释/回答一下
Originally posted by netwinxp at 2010-6-17 08:50 PM:
DOS下访问4G要先打开A20,否则访问偶数地址会出问题。
对头,需要打开A20地址线
Originally posted by netwinxp at 2010-6-17 08:50 PM:
To access 4G under DOS, you need to enable A20 first, otherwise, issues will occur when accessing even addresses.
Right, you need to enable the A20 address line
|
|
2010-6-17 22:22 |
|
|
johnsonlam
银牌会员
     阿林
积分 1410
发帖 497
注册 2004-6-28 来自 九龍,香港
状态 离线
|
『第 7 楼』:
使用 LLM 解释/回答一下
Originally posted by AlexZhang at 2010-6-17 10:22 PM:
对头,需要打开A20地址线
根 據 Jack Ellis 兄 所 說 , A20 控 制 原 來 也 挺 『 不 標 準 』 ...
1) Port 92h logic
2) keyboard-port logic
還 要 用 時 上 鎖 和 解 鎖 lock / unlock , 煩 !
Originally posted by AlexZhang at 2010-6-17 10:22 PM:
Exactly, need to enable the A20 address line
According to Brother Jack Ellis, the A20 control was originally quite 'non-standard'...
1) Port 92h logic
2) keyboard-port logic
Also need to lock and unlock from time to time, troublesome!
|

我 的 網 站 - http://optimizr.dyndns.org
|
|
2010-6-18 23:58 |
|
|
netwinxp
高级用户
   
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第 8 楼』:
使用 LLM 解释/回答一下
KBC是286以后的标准,92口不标准(它是MAC总线的标准,很多机子不能用,要在在BIOS SETUP把A20 Fast打开(如果有此项的话)才能支持),KBC法对x86通用,不过切换慢,而且有时会和USB键鼠冲突(写KBC A20位时要先禁止KBC数据缓冲区写入,写完后再去掉禁止,否则USB键鼠有可能错误写到KBC命令缓冲区造成USB键鼠失效)。
我最早看到的DOS下利用FS、GS访问4G是梁肇新(就是那个超级结巴的开发者)9x年写的“在DOS实模式下直接存取4GB内存”一文,现在的“砖家”抄袭够狠的,全成了“原创”。
实模式下访问4G的最大问题是——对于FFFF:FFFF以上内存没有管理,所以还是通过INT 15、XMS、EMS、DPMI稳妥。
Last edited by netwinxp on 2010-6-20 at 14:14 ]
KBC is a standard after 286. The 92 port is not standard (it is a standard for the MAC bus, many machines cannot use it, and you need to turn on A20 Fast in BIOS SETUP (if this option exists) to support it). The KBC method is universal for x86, but switching is slow, and sometimes it conflicts with USB keyboards and mice (when writing to the KBC A20 bit, you need to first prohibit writing to the KBC data buffer, and then remove the prohibition after writing, otherwise the USB keyboard and mouse may incorrectly write to the KBC command buffer and cause the USB keyboard and mouse to fail).
The first time I saw the use of FS and GS to access 4G under DOS was the article "Directly Accessing 4GB Memory in Real Mode of DOS" written by Liang Zhaoxin (that super stuttering developer) in 199x. Now the "experts" are so plagiaristic, all of them have become "original".
The biggest problem in accessing 4G in real mode is - there is no management for memory above FFFF:FFFF, so it is still safe to use INT 15, XMS, EMS, DPMI.
Last edited by netwinxp on 2010-6-20 at 14:14 ]
|
|
2010-6-20 13:59 |
|
|
gssxd
新手上路

积分 6
发帖 3
注册 2010-5-19
状态 离线
|
『第 9 楼』:
使用 LLM 解释/回答一下
<img src="images/smilies/face-raspberry.png" align="absmiddle" border="0">
Last edited by gssxd on 2010-6-21 at 22:42 ]
:P
Last edited by gssxd on 2010-6-21 at 22:42 ]
|
|
2010-6-21 22:40 |
|
|
gssxd
新手上路

积分 6
发帖 3
注册 2010-5-19
状态 离线
|
『第 10 楼』:
使用 LLM 解释/回答一下
Originally posted by netwinxp at 2010-6-20 13:59:
KBC是286以后的标准,92口不标准(它是MAC总线的标准,很多机子不能用,要在在BIOS SETUP把A20 Fast打开(如果有此项的话)才能支持),KBC法对x86通用,不过切 ...
关于A20 Disable以及Enable,还是要看BIOS里面的实现的。DOS下都是在调用INT15,BIOS提供的接口,属于Rumtime。BIOS在引导OS之前会把A20给Disbale。
Originally posted by netwinxp at 2010-6-20 13:59:
KBC is the standard after 286. The 92-pin port is non-standard (it is the standard of the MAC bus. Many machines cannot use it. You need to turn on A20 Fast in BIOS SETUP (if this option is available) to support it). The KBC method is universal for x86, but cutting ...
Regarding A20 Disable and Enable, it still depends on the implementation in the BIOS. Under DOS, it is all by calling INT15, the interface provided by the BIOS, which belongs to Runtime. The BIOS will disable A20 before booting the OS.
|
|
2010-6-21 22:47 |
|
|
netwinxp
高级用户
   
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第 11 楼』:
使用 LLM 解释/回答一下
CMOS里面的A20 Fast Enable/Disable是指提不提供92H口来快速切换A20的状态,如果Disable掉就不提供92H口,只能用慢速的KBC来切换,它和A20 Enable/Disable不是一回事。INT 15H事实上也是通过KBC或者92H口来操作。至于所谓的FireWare Runtime其实也就是把总线操作、I/O操作、所需数据用ASL(微软要求的格式)包装起来方便windows acpi操作硬件罢了,本质上和以前的APM差不多,只不过APM通过INT 15H调用,需切换到实模式(比如win98的关机),windows可以在保护模式通过ACPI根据ASL定义来操作硬件而已。ASL是微软提供标准和工具,说白了也就形成变相上的垄断,看看linux在实现ACPI上走了多少弯路不就明白了?其实如果里面放的是没经过“故意编译”的脚本,别的操作系统实现起来也不难了。
Last edited by netwinxp on 2010-6-22 at 18:52 ]
In the CMOS, A20 Fast Enable/Disable refers to whether to provide the 92H port to quickly switch the state of A20. If it is disabled, the 92H port is not provided, and only the slow KBC can be used to switch. It is not the same as A20 Enable/Disable. In fact, INT 15H also operates through the KBC or 92H port. As for the so-called FireWare Runtime, it is just packaging bus operations, I/O operations, and required data in the ASL (format required by Microsoft) to facilitate Windows ACPI to operate hardware. Essentially, it is similar to the previous APM. The difference is that APM is called through INT 15H and needs to switch to real mode (such as shutting down in win98). Windows can operate hardware in protected mode through ACPI according to the ASL definition. ASL is a standard and tool provided by Microsoft. To put it simply, it forms a de facto monopoly. Just look at how many detours Linux has taken in implementing ACPI to understand it! In fact, if the script inside is not "deliberately compiled", it is not difficult for other operating systems to implement it.
Last edited by netwinxp on 2010-6-22 at 18:52 ]
|
|
2010-6-22 18:25 |
|
|