TIP: Click on subject to list as thread! ANSI
echo: 80xxx
to: DARRYL GREGORASH
from: SERGUEI SHTYLIOV
date: 1997-12-18 10:17:00
subject: extended memory

Haill!
Once you wrote to me:
 JW>>>> mov     ax,0
 JW>>>> mov     ds,ax       ;DS =
 JW>>>> mov     word ptr [ds:0b8142h],8403h
 DG>>> Out of idle curiosity, what happens if you try this without
 DG>>> himem.sys loaded?
 SS>> #GP will be generated.
 DG> No kidding.
   I'm serious -- it'll cause #GP (int 0Dh) even in real mode.
 DG>>> I ask, because I have been reading Intel specs for years,
 DG>>> and haven't got a clue what this "Big Real" mode is
 DG>>> supposed to be.
 SS>> It is still undocumented by Intel of course. :)
 DG> I'm from Missouri. What is the opcode mnemonic to switch to this mode?
   _Opcodes_ you mean. There's no special opcodes, just plain vanilla ones. 
)
Here's the short example (with my comments in []):
- - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - 
-
                .model  tiny
                .code
                org     100h
                .386p
;
; How to setup the BIG REAL MODE
; Copyright (C) Aleksandr K. Konosevich, 1997, V 0.2
; Note : this example sets 4Gb limit _for_all_segment_registers_
;
start:
                dd      0E0010F66h              ;)
                                                ; [this is the SMSW EAX
                                                ; instruction, using it isn't
                                                ; necessary but there's smth
                                                ; interesting about the way 
t
                                                ; works :)]
                test    al, 01h                 ; [CR0.PE=1?]
                jnz     exit                    ; [forget it, we're in V86]
                mov     edx, cs                 ;)
                                                ; [MOV Reg32,SegReg clears 
he
                                                ; high word of Reg32]
                push    ss                      ;(
                shl     edx, 4
                add     dword ptr GDT_base, edx ; [adjust GDT base]
                or      dword ptr CS_base, edx  ;)
                                                ; [and flat segment's base 
too]
                inc     ax                      ; [set CR0.PE]
                cli
                lgdt    qword ptr GDT_base-2    ;)
                                                ; [dirty trick (: GDT limit
                                                ; will be set to 21CDh (int 
21h
                                                ; opcode) which is quite 
enough
                                                ; for us]
                mov     cr0, eax                ; [enter PM]
                mov     dx, 08h                 ; [GDT descriptor 1: flat 4G
                                                ; data segment]
                mov     ds, dx                  ; [load it into 
DS,ES,FS,GS,SS]
                mov     es, dx
                mov     gs, dx
                mov     fs, dx
                mov     ss, dx
                or      byte ptr CS_base+3, dl  ;)
                                                ; [now turn the data segment
                                                ; into the code segment]
                db      0EAh                    ; [and do a FAR jump]
                dw      offset set_CS           ; [to load CS from 4G flat]
                dw      8                       ; [segment descriptor]
set_CS:
                dec     ax                      ; [clear CR0.PE]
                mov     cr0, eax                ; [enter RM again]
                pop     ss                      ;(
                                                ; [SS needs to be restored,
                                                ; remember: CPU even in RM 
uses
                                                ; the segment base from the
                                                ; segment descriptor caches,
                                                ; and ignores the segment
                                                ; registers' contents, so POP 
; as well as any other memory
                                                ; reference works relative to
                                                ; the program load address, ; 
not 80h as you may judge                                                ; by 
the current segment
                                                ; registers' contents ;) ]
exit:
                mov     ah, 4Ch                 ; [we did it! but CS!=PSP, so
                                                ; we can't use INT 20h or 
ETN
                                                ; to exit]
                int     21h
GDT_base        dd      offset GDT_base-4       ;)
                                                ; [those -4 is for the "null
                                                ; descriptor -- it's contents
                                                ; is irrelevant to the CPU]
                dw      0FFFFh                  ; [low word of the 
descriptor's
                                                ; limit]
CS_base         dd      92000000h               ; [writeable data segment]
                dw      008Fh                   ; [with 4K granularity]
                end     start
- - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - 
-
   Well, about that SMSW EAX thing: on Intel CPUs it functions just like MOV 
EAX,CR0 except it doesn't generate #GP when executed not on the CPL0 (and in 
V86 mode) -- it returns not only low word of CR0 (i.e. 286's MSW) but its 
high word too, including CR0.PG and other 386+ bits. On Intel clones like AMD 
this bug has been fixed, so the high word is always 0. BTW, when you check 
for V86 from a DOS program, always use SMSW and never MOV Reg32,CR0 beacuse 
the latter will generate #GP which some VM monitors (e.g. Win3.x/Win'95) 
handle rather improperly -- the just skips the whole instruction not changing 
Reg32 contents!
 DG>>> There are 2 modes on Intel 32-bit CPUs, 16 and 32. The
 DG>>> former has one flavour only, and looks basically like one
 DG>>> big DOS machine,
 SS>> Plain RM but not BRM: first, the segment limits may be
 SS>> set to 4G (or anything you like); second, you can change
 SS>> B-bit in the segment descriptor caches so you segments can
 SS>> be 32-bit even in RM (and AFAIK this can be done even with
 SS>> CS though requires some tricks for correct interrupt
 SS>> entering/ exitting)!
 DG> No kidding, particularly since descriptors don't exist in "real" mode.
    Actually they do: the "descriptor caches" are still here and working. 
Reloading the segment register in RM usually reloads only the segment's base
address in those caches, leaving segment limits unchanged; the other fiels 
could be changed by entering PM and loading the segment registers with 
appropriate selectors, and the exiting to RM as in the above example. Well, 
here's some stuff about those things by Robert Collins:
- - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - 
-
        Page    60,132
        Title   Descriptor Cache Anomalies
;-----------------------------------------------------------------------------
;
; DESC32.ASM
;
;       Copyright (c) 1991, 1995-Present  Robert Collins
;
;       You have my permission to copy and distribute this software for
;       non-commercial purposes.  Any commercial use of this software or
;       source code is allowed, so long as the appropriate copyright
;       attributions (to me) are intact, *AND* my email address is properly
;       displayed.
;
;       Basically, give me credit, where credit is due, and show my email
;       address.
;
;-----------------------------------------------------------------------------
;
;       Robert R. Collins               email:  rcollins@x86.org
;
;-----------------------------------------------------------------------------
; DESCRIPT.ASM -- Prove that anomalies exist in the real mode definition of
;                 the descriptor cache registers.  Intel states that all of
;                 these registers get default, fixed values when loaded in
;                 real mode.  This is not the case, and this source code
;                 will attempt to prove that.
;
;                 Unfortunately, most of these cases are impossible to prove
;                 under software control -- and can only be proven using an
;                 Intel ICE.
;
;-----------------------------------------------------------------------------
;
;       +-----------------------------------------------+
;       | Descriptor Cache contents:  Real-Mode         |
;       |                                               |
;       |     Operand size(*)-------------------------+ |
;       |     Granularity(*)------------------------+ | |
;       |     Accessed----------------------------+ | | |
;       |     Read/Write------------------------+ | | | |
;       |     Expansion direction-------------+ | | | | |
;       |     Executable--------------------+ | | | | | |
;       |     Code/Data Segment?----------+ | | | | | | |
;       |     Privilege level----------++ | | | | | | | |
;       |     Present----------------+ || | | | | | | | |
;       |                            | || | | | | | | | |
;       |     Base Addr    Limit     | || | | | | | | | |
;       | ---+------------+---------+-+--+-+-+-+-+-+-+-+|
;       | CS |16xSeg. Reg.| Honored |Y| H|Y|H|H|Y|Y|-|H||
;       | ---+------------+---------+-+--+-+-+-+-+-+-+-+|
;       | SS |16xSeg. Reg.| Honored |H| H|Y|H|H|H|Y|-|-||
;       | ---+------------+---------+-+--+-+-+-+-+-+-+-+|
;       | DS |16xSeg. Reg.| Honored |H| H|Y|H|H|H|Y|-|-||
;       | ---+------------+---------+-+--+-+-+-+-+-+-+-+|
;       | ES |16xSeg. Reg.| Honored |H| H|Y|H|H|H|Y|-|-||
;       | ===+============+=========+=+==+=+=+=+=+=+=+=+|
;       | FS |16xSeg. Reg.| Honored |H| H|Y|H|H|H|Y|-|-||
;       | ---+------------+---------+-+--+-+-+-+-+-+-+-+|
;       | GS |16xSeg. Reg.| Honored |H| H|Y|H|H|H|Y|-|-||
;       | ---+------------+---------+-+--+-+-+-+-+-+-+-+|
;       |                                               |
;       | Y=Yes    (1)                                  |
;       | N=No     (0)                                  |
;       | U=Up     (0)                                  |
;       | B=Byte   (0)   (*)=386 and 486 only           |
;       | S=16-bit (0)   (*)=386 and 486 only           |
;       | H=Honored.  Whenever the segment gets loaded, |
;       |             the contents of this field don't  |
;       |             change.                           |
;       | -=Not applicable                              |
;       |                                               |
;       +-----------------------------------------------+
;
- - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - - 8<- - - - 
-
   The whole source is available at ftp.x86.org (or I could post it here).
 DG>>> If you try this code in 16-bit mode, you will definitely
 DG>>> get a CPU exception,
 SS>> You won't, if you use those BRM tricks. :)
 DG> Show me the opcodes.
   Well, after executing the above exapmle in RM (not in V86 mode, of course) 
you'll be able to access the data beyond 64K segment limits using any segment 
prefix.
 DG>>> I can't recall the number, but it will be a segment
 DG>>> boundary violation.
 SS>> Int 13 - GP fault (#GP).
 DG> General protection fault in native mode; in "real" mode, only a segment
 DG> boundary violation generates the interrupt.
   But it's the same #GP, isn't it? :)
 DG>>> It is possible that Himem.sys traps that exception... kicks the
 DG>>> system into 32-bit mode,
 SS>> No, it "kicks the system" to PM,
 DG> "Protected" mode = native mode = 32-bit mode.
   It uses 16-bit mode as it just doesn't need 32-bit mode to load DS/ES with 
the flat segment's descriptor and exit PM.
 SS>> then loads DS/ES with 4G
 SS>> segment selector, then returns to RM. The new segment
 SS>> limits are honored in RM
 DG> Selectors do not even exist in "real" mode.
   1) don't confuse the selectors and the descriptors;
   2) don't confuse segment descriptrs in the GDT/LDT, and their "mirrors" in 
the segment "shadow registers" (AKA descriptor caches), the latter do exist 
even in RM.
 SS>> -- segment reg. re-loads doesnt'
 SS>> change them. That's why it all works after HiMem does a
 SS>> block move.
 DG> Time to disassemble himem.sys, I think.. more likely the INT D trap in
 DG> himem performs the block move, then returns to "real" mode.
   Well, try this. I'm posting XM386.ASM (HiMem 386+ memory move part) in the 
next message(s)...
Farewell!
--- GoldED 2.50+
---------------
* Origin: Six To Go (FidoNet 2:5020/157.59)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.