flat assembler
Message board for the users of flat assembler.

Index > DOS > Starting devel for DOS with FASM (DPMI32)

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 08 Dec 2006, 18:43
I intentionally start a new thread - did read the other (real mode) one

Trying to start coding for DOS in ASM. Tried several high lang compilers
before and results were frustrating Embarassed (HELLO.EXE 100 KiB !!!, DOS
host & target unsupported, buggy, dead, ...).

Prefer DPMI32 from real mode.

Code:
; fasm example of writing 32-bit program using DPMI

; requires DPMI host installed in system

format MZ
heap 0                                  ; no additional memory

segment loader use16

        push    cs
        pop     ds

        mov     ax,1687h
        int     2Fh
        or      ax,ax                   ; DPMI installed?
        jnz     error1
        test    bl,1                    ; 32-bit programs supported?
        jz      error2
        mov     word [mode_switch],di
        mov     word [mode_switch+2],es
        mov     bx,si                   ; allocate memory for DPMI data
        mov     ah,48h
        int     21h
        jc      error3
        mov     es,ax
        mov     ax,1
        call    far [mode_switch]       ; switch to protected mode
        jc      error3

        mov     cx,1
        xor     ax,ax
        int     31h                     ; allocate descriptor for code
        mov     si,ax
        xor     ax,ax
        int     31h                     ; allocate descriptor for data
        mov     di,ax
        mov     dx,cs
        lar     cx,dx
        shr     cx,8
        or      cx,0C000h
        mov     bx,si
        mov     ax,9
        int     31h                     ; set code descriptor access rights
        mov     dx,ds
        lar     cx,dx
        shr     cx,8
        or      cx,0C000h
        mov     bx,di
        int     31h                     ; set data descriptor access rights
        mov     ecx,main
        shl     ecx,4
        mov     dx,cx
        shr     ecx,16
        mov     ax,7                    ; set descriptor base address
        int     31h
        mov     bx,si
        int     31h
        mov     cx,0FFFFh
        mov     dx,0FFFFh
        mov     ax,8                    ; set segment limit to 4 GB
        int     31h
        mov     bx,di
        int     31h

        mov     ds,di
        mov     es,di
        mov     fs,di
        mov     gs,di
        push    0
        push    si
        push    dword start
        retfd

    error1:

        mov     dx,error1t
        jmp     waaa

    error2:     

        mov     dx,error2t
        jmp     waaa
    
    error3:

        mov     dx,error3t

    waaa:
        
        mov     ah,9
        int     21h

        mov     ax,4CFFh
        int     21h

error1t db 'Fool! No DPMI!',24h
error2t db 'Fool! DPMI is 16 bit only!',24h
error3t db 'Fool! Fatal DPMI problem',24h

  mode_switch dd ?

segment main use32

  start:
        mov     esi,hello
    .loop:
        lodsb
        or      al,al
        jz      .done
        mov     dl,al
        mov     ah,2
        int     21h
        jmp     .loop
    .done:

        mov     ax,4C00h
        int     21h

  hello db 'Hello from protected mode!',0Dh,0Ah,0
    


Added 3 error messages to original code and seems to work like a charm Smile
(could verify only 2 of them).

Some questions:

- Is FASM a good choice for 32-bit DOS development ?

YES !

- FASM itself seems to be coded in a rare and weird (in a positive sense)
way - 16-bit MZ EXE, no DOS extender, runs on "raw" DPMI if available,
in unreal mode otherwise (failure on EMM386 ?) - is this correct ?

NO - prefers unreal from DPMI (may fail in some cases)

- What DOS extender should I use ? Well, I already reduced the number
of candidates to cca 2:
- DOS/32A
- HDPMI32
There seem to be 2 fundamentally different approaches:
- WATCOM-like (DOS extender merged with DPMI kernel), followed by LE-EXE
- DGJPP-like (COFF executable including the extender, DPMI kernel separated)
Is both possible with FASM ? What is better ?

All is possible (WATCOM/LE-like, HDPMI32-like-raw, HDPMI32-like-PE, CWSDPMI-like) , see : http://board.flatassembler.net/topic.php?t=8670 , HDPMI32 is most likely the best way

The USEDPMI example exposes excellent efficiency (my improved
USEDPMI.EXE "Hello" has 341 bytes (instead of 100 KB Rolling Eyes), but
possibly has a problem: limits code size to 64 KB. What is the best way to
get >64KB for code ? Question

MZ-32 (but low memory limits), WATCOM/LE, LOADPEX/PE, load raw flat (see below)

EDIT (2008-05-03, 1+1/2 years later Shocked ) : Answered my questions, in RED


Last edited by DOS386 on 03 May 2008, 16:40; edited 1 time in total
Post 08 Dec 2006, 18:43
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 08 Dec 2006, 19:36
NTOSKRNL_VXE wrote:
The USEDPMI example exposes excellent efficiency (my improved
USEDPMI.EXE "Hello" has 341 bytes (instead of 100 KB Rolling Eyes), but
possibly has a problem: limits code size to 64 KB.

No, it doesn't. It limits code to about 600 KB, as the MZ EXE has to be loaded into conventional memory, however it doesn't limit you to 64 KB segment limit.
Code:
segment main use32

        times 70000 nop

  start:
        mov     esi,hello
    .loop:
        lodsb
        or      al,al
        jz      .done
        mov     dl,al
        mov     ah,2
        int     21h
        jmp     .loop
    .done:

        mov     ax,4C00h
        int     21h

  hello db 'Hello from protected mode!',0Dh,0Ah,0    
Post 08 Dec 2006, 19:36
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 08 Dec 2006, 20:01
Quote:

No, it doesn't. It limits code to about 600 KB, as the MZ EXE has to be loaded into conventional memory, however it doesn't limit you to 64 KB segment limit.

Code:
segment main use32

        times 70000 nop

  start: 
    



Thanks.

Tried the 70'000 NOP hack - works. Does it mean that DOS MZ executable
can contain blocks >64 KB and DOS is supposed to load them correctly ?

Nevertheless: One could need more than 600 KB (for included multimedial
data rather than for code Wink) - What is the best way to do ?

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 08 Dec 2006, 20:01
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 08 Dec 2006, 20:12
NTOSKRNL_VXE wrote:
Tried the 70'000 NOP hack - works. Does it mean that DOS MZ executable
can contain blocks >64 KB and DOS is supposed to load them correctly ?

The complete MZ executable is always loaded into a continuous memory block, no matter how large it is.

NTOSKRNL_VXE wrote:
Nevertheless: One could need more than 600 KB (for included multimedial
data rather than for code Wink) - What is the best way to do ?

You can put your data as an overlay into your MZ program (in the same way as PE executable is built on top of the MZ one) and load it yourself into extended memory after the program starts.
Post 08 Dec 2006, 20:12
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 08 Dec 2006, 21:42
Thanks.

Quote:

You can put your data as an overlay into your MZ program (in the same way as PE executable is built on top of the MZ one) and load it yourself into extended memory after the program starts.


Like DOS extenders do. But, when using ASM, is there a need or benefit from
using a complete DOS extedner (like DOS/32A), or is using of "raw" DPMI
better ?

Will the DPMI kernel (prefer HDPMI32, do not bother about lacks of others)
itself handle interrupts (mouse driver, keyboard, ...) correctly ?

Can I simply access INT's from DPMI code in exactly same way as from
real mode ?

Code:
segment main use32

        times 70000 nop

  start:
        mov     esi,hello   ;In  PM now ...
    .loop:
        lodsb
        or      al,al
        jz      .done
        mov     dl,al
        mov     ah,2
        int     21h    ;simple INT will always work ????
        jmp     .loop
    .done:

        mov     ax,4C00h    ;exit now - but switch back to RM ?
        int     21h

  hello db 'Hello from protected mode!',0Dh,0Ah,0
    


Where does the switch back to real mode occur ?

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 08 Dec 2006, 21:42
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 08 Dec 2006, 22:40
NTOSKRNL_VXE wrote:
Like DOS extenders do. But, when using ASM, is there a need or benefit from
using a complete DOS extedner (like DOS/32A), or is using of "raw" DPMI
better ?

The advantage of using a complete extender is that you are not dependent on DPMI server having to be installed in system. On the other hand, when there is a DPMI server, using an additional extender may be a waste of resources.

Also, if the server implements only the official DPMI 0.9 (or even 1.0) services (it's this way with CWSDPMI, for example), the extender may have another advantage, that it may implement some of features of what I heard sometimes called True DPMI. As I once read, it was as set of functions in the first draft of DPMI, removed during the standard defining process. It included the 32-bit versions of the most of interrupt 21h functions, which would be a great thing if it was a standard, however it never made it into official specifications. But the fact is, that some of the DPMI implementations made by companies that perhaps knew the initial design of the DPMI, include the TrueDPMI services. Such ones that I'm aware of is the DOS subsystem of Windows, and the QDPMI server by Quarterdeck.

NTOSKRNL_VXE wrote:
Will the DPMI kernel (prefer HDPMI32, do not bother about lacks of others)
itself handle interrupts (mouse driver, keyboard, ...) correctly ?

Can I simply access INT's from DPMI code in exactly same way as from
real mode ?

The DPMI by default forwards all the interrupts to their real-mode handlers (unless you install your own 32-bit handler for some interrupt), thus when interrupt occurs, it switches either to V86 or real mode (depending on the implementation) and call the real-mode handler for that interrupt. The general registers are passed unchanged to that handler. Thus the function 2 of interrupt 21h in the example is called through the DPMI forwarding and it appears to be working just as if you called it from real mode.
However the problem arises when you need to pass addresses - since in protected mode you've got selectors, while in real mode you've got segments. Thus if you called an interrupt function that needs an address among it parameters, you have to somehow pass the segmented address to the real-mode handler to get it working.

To help calling the interrupt functions with pointers as parameters, there's a DPMI function 300h, which you can use to define exactly contents of all segment registers and general registers that should be passed to real-mode interrupt handler. The use of this function is a bit more complicated than calling the interrupt directly - see the "dpmi_dos_int" routine in the DOS/SYSTEM.INC file in fasm's sources.

If the DPMI server supports the True DPMI services, as the one in Windows' subsystem does, the thing is much more simpler, however. The functions of interrupt 21h have their 32-bit versions implemented, and thus you can do things simply like:
Code:
  ; WARNING: works only with True DPMI

  start:
        mov     edx,hello
        mov     ah,9
        int     21h

        mov     ax,4C00h
        int     21h

  hello db 'Hello from protected mode!',0Dh,0Ah,'$'    
Post 08 Dec 2006, 22:40
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 08 Dec 2006, 23:40
Code:
            mov  ax,4C00h
            int     21h
    


Does it mean that this INT switches back to real mode, whether the
DPMI is true or not ?

Quote:
However the problem arises when you need to pass addresses


I see. That is why the PM hello prints text letter by letter,
with one INT per letter.

The question is: does HDPMI provide TrueDPMI ?

Code:
 
6.8 DOS API Translation

   HDPMI supports DOS-API translation, both in 16-bit mode and in
   32-bit mode. For translation purposes, HDPMI allocates a static
   translation buffer of 8 KB. For the important read/write functions
   HDPMI will try to allocate a temporary 64k buffer, if the size of
   the i/o-operation exceeds the size of the static translation buffer.
    


Is ^^ this ^^ the same as TrueDPMI ?

How to read my data into the DPMI memory ?

Could you please provide a simple example:

- Allocate 4 MB of DPMI memory
- Zeroize it
- Read (file supposed already opened) 2 MB from a file into this memory
- Jump to the begin of this 2 MB block

Will code in this memory automatically work (32bit "raw" code) or are
there additional problems ?

My example executable (just to make sure the method will work for
everything I might code in future) could look following way:

- cca 1 KB small 16-bit "stub"
- cca 1 MB of code (1 MB is VERY much code Wink I know)
- cca 1 MB of multimedial data

The stub should:

- Verify system requirements (I have some ideas/examples/hints how to do this)
- Switch to PM
- Allocate 4 MB of DPMI memory
- read the 1+1 MB from my file (skipping the "stub") into this DPMI memory
- jump to this code

The final 32-bit code in DPMI memory would access the 1 MB of my MM
data and use the free 2 MB for temporary buffers.

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 08 Dec 2006, 23:40
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 09 Dec 2006, 00:26
Tested:

Code:
 ; WARNING: works only with True DPMI

  start:
        mov     edx,hello
        mov     ah,9
        int     21h

        mov     ax,4C00h
        int     21h

  hello db 'Hello from protected mode!',0Dh,0Ah,'$'
    


HDPMI32: Works Smile This is GOOD

CWSDPMI: Failure (huge mess printed, then exits) This is irrelevant ...

But still I'd like to know how to read from a file into DPMI memory
and execute code there in (see post above).

EDIT: removed split request

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug


Last edited by DOS386 on 09 Dec 2006, 20:20; edited 3 times in total
Post 09 Dec 2006, 00:26
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 14 Dec 2006, 00:38
I experimented with the example:

1
Code:
; fasm example of writing 32-bit program using HDPMI32

format MZ
heap 0                   ; no additional memory
stack 4000h

stubsize = 400h       ;guess Wink

qpsp    = stubsize        ;2 bytes
qmodesw = stubsize + 2    ;4 bytes

segment uselessdummylabel1 use16

        mov    ax,ds              ;save DS - contains PSP addr !!!

        push    cs
        pop     ds

        mov    word [qpsp],ax     ;save here

;#########################################

        mov     ax,1687h
        int     2Fh
        or      ax,ax                   ; DPMI installed?
        jnz     error1
        test    bl,1                    ; 32-bit programs supported?
        jz      error2
        mov     word [qmodesw],di
        mov     word [qmodesw+2],es
        mov     bx,si                   ; allocate memory for DPMI data
        mov     ah,48h
        int     21h
        jc      error3
        mov     es,ax
        mov     ax,1
        call    far [qmodesw]           ; switch to protected mode !!!!!!!!!!!!!!!!!!!!!!!!!
        jc      error3
    


2
Code:
        mov     cx,1
        xor     ax,ax
        int     31h                     ; allocate descriptor for code
        mov     si,ax
        xor     ax,ax
        int     31h                     ; allocate descriptor for data
        mov     di,ax
        mov     dx,cs
        lar     cx,dx
        shr     cx,8
        or      cx,0C000h
        mov     bx,si
        mov     ax,9
        int     31h                     ; set code descriptor access rights
        mov     dx,ds
        lar     cx,dx
        shr     cx,8
        or      cx,0C000h
        mov     bx,di
        int     31h                     ; set data descriptor access rights
        mov     ecx,main32a
        shl     ecx,4
        mov     dx,cx
        shr     ecx,16
        mov     ax,7                    ; set descriptor base address
        int     31h
        mov     bx,si
        int     31h
        mov     cx,0FFFFh
        mov     dx,0FFFFh
        mov     ax,8                    ; set segment limit to 4 GB
        int     31h
        mov     bx,di
        int     31h

        mov     ds,di
        mov     es,di
        mov     fs,di
        mov     gs,di
        push    0
        push    si
        push    dword 0         ;& jump to main32 - relative addr is 0 !!!
        retfd                   ;&
    


3
Code:
    error1:

        mov     dx,error1t
        jmp     @f

    error2:     

        mov     dx,error2t
        jmp     @f
    
    error3:

        mov     dx,error3t
        
@@:     mov     ah,9
        int     21h

        mov     ax,4CFFh      ;Ending with a FAILURE Sad
        int     21h

error1t db 'Fool! No DPMI!',24h
error2t db 'Fool! DPMI is 16 bit only!',24h
error3t db 'Fool! Fatal DPMI problem!',24h
    


4
Code:
segment main32a use32

              mov    ah,9
              mov    edx,thello
              int 21h
              jmp short @f

thello db 'Hello from protected mode!',0Dh,0Ah,24h

@@:     mov     ax,4C00h
        int     21h

;========================================================

        rb 4000h

;========================================================
    


Could someone explain me:

- What does block 2 do ? We are (?) already in PM at begin of this block ...
- Is the jump to block 4 required ? Why is it workarounded with RETFD - JMP would not work ?
- How to allocate a large amount of DPMI memory, load a file (a "flat"/"raw" code file, no messy COFF) into it, and execute code there ?

Quote:

"segment" directive defines a new segment, it should be followed by label,
which value will be the number of defined segment, optionally "use16" or
"use32" word can follow to specify whether code in this segment should be
16-bit or 32-bit. The origin of segment is aligned to paragraph (16 bytes).
All the labels defined then will have values relative to the beginning of this
segment.


What value will label "main32a" have ? 1 according to this text ?

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 14 Dec 2006, 00:38
View user's profile Send private message Reply with quote
Japheth



Joined: 26 Oct 2004
Posts: 151
Japheth 14 Dec 2006, 09:52
> - Is the jump to block 4 required ? Why is it workarounded with RETFD - JMP would not work ?

yes, it switches from 16-bit to 32-bit CS. RETFD is used because the segment part of the far address is unknown at link time and therefore it is the simplest method to do a far jump. A simple RETF would also work here, however:

Code:
        push    si
        push    0
        retf 
    


- How to allocate a large amount of DPMI memory

there exists dpmi function int 31h, ax=0x501 for this task.

> load a file (a "flat"/"raw" code file, no messy COFF) into it

if the DPMI host implements DOS API translation, it is as simple as in real-mode DOS. indeed even more simple, because int 21h, ah=3Fh will understand DS:EDX as buffer address and ECX as bytes to read.

> and execute code there

you will have to setup a code/data descriptor the way it is done in "2".
Post 14 Dec 2006, 09:52
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 14 Dec 2006, 20:55
Thanks.

Code:
segment main32a use32

              mov    ah,9
              mov    edx,t1
              int 21h
              jmp short @f

t1 db 'Hey ... not yet hello ... trying to allocate INT 31,501 !',0Dh,0Ah,24h

@@:           mov bx,40h          ;BX is high
              mov cx,0            ;CX is low 4MB
              mov ax,0501h 
              int 31h      ;BX:CX = linear address of allocated memory block
              jnc @f       ;OK

              mov    ax,0900h
              mov    edx,t2
              int 21h
              jmp short qend

t2 db 'INT 31,501 ran in a failure !!!',0Dh,0Ah,24h

@@:           mov    ax,0900h
              mov    edx,t3
              int 21h
              jmp short qend

t3 db 'INT 31,501 success !',0Dh,0Ah,24h


qend:       mov     ax,4C00h
            int     21h

;========================================================

        rb 4000h

;========================================================
    


Quote:

- How to allocate a large amount of DPMI memory
there exists dpmi function int 31h, ax=0x501 for this task.


Seems to work. BX:CX, higher 16 bits in BX and lower 16 bits in CX.

But how to activate it, so that I can write into it, and execute code there ?

Quote:
you will have to setup a code/data descriptor the way
it is done in "2".


That's what I expected Rolling Eyes ... any info or examples how to do this ?
Need to reduce "segment limit" in "2" from 4 GB to 4 KB ?

Quote:
if the DPMI host implements DOS API translation


You call it "DOS API translation", Tomasz Grysztar calls it "TrueDPMI",
seems to be same thing and to work. Smile

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 14 Dec 2006, 20:55
View user's profile Send private message Reply with quote
Japheth



Joined: 26 Oct 2004
Posts: 151
Japheth 14 Dec 2006, 22:03
> That's what I expected Rolling Eyes ... any info or examples how to do this ?

"2" can be used, just replace the "main32a" by the linear address returned by the 0x501 function. Don't care about the segment limit, 4 GB is good as a start.

of course, before executing the RETFD, dont forget to first read your precious code into the memory:

Code:
        mov     ds,di
        mov     es,di
        mov     fs,di
        mov     gs,di
        push    0
        push    si
        push    dword 0         ;& jump to offset 0

        mov    bx, ??? 
        mov    edx,0
        mov    ecx,400000h
        mov    ah,3Fh
        int 21h
        jc        didntwork
        retfd
    
Post 14 Dec 2006, 22:03
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 14 Dec 2006, 23:19
Thanks.

Quote:

"2" can be used, just replace the "main32a" by the linear address returned by the 0x501 function.


"BX:CX" - Higher 16 bits in BX and lower 16 bits in CX again (double BIG
endian Very Happy ?) ?

Put it together and push into ECX instead "main32a" label ?

Quote:

Don't care about the segment limit, 4 GB is good as a start.


Can I have many segments at same time, all with 4 GB limit ? What I
wanted to reduce to 4 KB was the original "4" segment in "low"/DOS
memory, not my new (4 MB so far in examples above) one.

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 14 Dec 2006, 23:19
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 14 Dec 2006, 23:21
NTOSKRNL_VXE wrote:
You call it "DOS API translation", Tomasz Grysztar calls it "TrueDPMI", seems to be same thing and to work. Smile

I started using the term "True DPMI" after reading this excellent lecture somewhere around 1999:
http://lists.gnu.org/archive/html/lynx-dev/1998-04/msg00773.html
It's more about the history than technical stuff, however I really recommend reading this.
Post 14 Dec 2006, 23:21
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 16 Dec 2006, 20:12
Code:
        mov     ds,di
        mov     es,di
        mov     fs,di
        mov     gs,di
        push    0
        push    si
        push    dword 0         ;& jump to offset 0

        mov    bx, ??? 
        mov    edx,0
        mov    ecx,400000h
        mov    ah,3Fh
        int 21h
        jc        didntwork
        retfd
    


Tried to write the code using hints provided but ran into a
fundamendal problem:

How to access 2 segments at same time ?

All code before "retfd" must run in "old" segment
Filename is stored in the old one
Contents of the file must read to the new one
If reading fails continue in old segment
Print error text stored in old segment
Exit correctly from old segment

How to "switch" or get around this ? Question

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 16 Dec 2006, 20:12
View user's profile Send private message Reply with quote
Japheth



Joined: 26 Oct 2004
Posts: 151
Japheth 17 Dec 2006, 09:13
> but ran into a fundamendal problem:

where is it? you must call int 21h, ah=3Fh with DS set to the new segment, but anything else can be stored/done in the old one.

Code:
        jmp @F
binname db ".\code32.bin",0
@@:
        mov     edx, binname
        mov     ax,3D00h
        int        21h
        jc         openfailed

        mov     ds,di
        mov     es,di
        mov     fs,di
        mov     gs,di
        push    0
        push    si
        push    dword 0         ;& jump to offset 0

        mov    bx, ax 
        mov    edx,0
        mov    ecx,400000h
        mov    ah,3Fh
        int 21h
        pushf
        mov ah,3Eh
        int 21h
        popf 
        jc        readfailed
        retfd
openfailed:
        mov   edx,openerr
        mov   ah,9
        int      21h
        mov    ax,4cffh
        int 21h
readfailed:
        push ds
        pop cs
        mov   edx,readerr
        mov   ah,9
        int      21h
        mov    ax,4cffh
        int 21h
openerr db "file not found",13,10,'$'
readerr db "read error",13,10,'$'

    
Post 17 Dec 2006, 09:13
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 19 Dec 2006, 14:20
Quote:

> but ran into a fundamendal problem:
where is it? you must call int 21h, ah=3Fh with DS set to the new segment, but anything else can be stored/done in the old one.


Thanks. I'll retry.

Code:
 mov     ds,di
    


Then ^^^ this ^^^ is the instruction switching the segment. Idea

Does it mean that all the preparation of the "new" segment does not
affect the "old" one, and the only thing I have to care about is to set
the "ds" correctly ?

Code:
readfailed:
        push ds      ;!!!
        pop cs       ;!!!
        mov   edx,readerr
        mov   ah,9
        int      21h
        mov    ax,4cffh
        int 21h 
    


Is this correct ? I could follow the code if the 2 lines were swapped Question

Code:
        mov     es,di
        mov     fs,di
        mov     gs,di
    


What is the goal of the "es", "fs", "gs" ?

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 19 Dec 2006, 14:20
View user's profile Send private message Reply with quote
Japheth



Joined: 26 Oct 2004
Posts: 151
Japheth 19 Dec 2006, 17:51
> Does it mean that all the preparation of the "new" segment does not

Yes


> push ds ;!!!
> pop cs ;!!!

IIRC "pop cs" does no longer exist on cpus > 8086.

> What is the goal of the "es", "fs", "gs" ?

it was *your* source which contained this stuff, I just added some lines. So you should ask yourself about the goal Smile.
Post 19 Dec 2006, 17:51
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 19 Dec 2006, 18:14
Quote:

> push ds ;!!!
> pop cs ;!!!

IIRC "pop cs" does no longer exist on cpus > 8086.


Means "cs" and "ds" should be swapped (but not the complete lines as
I wrote above) ... Shocked

Quote:
it was *your* source which contained this stuff, I just added some lines. So you should ask yourself about the goal


It is not really *my* source, it is the "USEDPMI" example ...

Code:
;       DPMICL32.ASM NASM Sample for a 32-bit DPMI client.
;       To assemble, use:
;               nasm dpmicl32.asm -O 2 -f obj -o dpmicl32.obj
;
;       To link, use:
;               valx /32 dpmicl32.obj;

LF      equ     10
CR      equ     13

        cpu     386

        segment _text use16 public class=CODE
    
..start:
        mov ax, dgroup
    mov ds, ax
    mov ax, ss
    mov cx, es
    sub ax, cx
    mov bx, sp
    shr bx, 4
    add bx, ax          ;release unused DOS memory
        mov ah, 4Ah
    int 21h
    mov ax, 1687h       ;DPMI host installed?
    int 2Fh
    and ax, ax
    jnz nohost
    push es                     ;save DPMI entry address
    push di
    and si, si          ;requires host client-specific DOS memory?
    jz nomemneeded
    mov bx, si
    mov ah, 48h         ;alloc DOS memory
    int 21h
    jc nomem
    mov es, ax
nomemneeded:
        mov bp, sp
    mov ax, 0001        ;start a 32-bit client
    call far [bp]       ;initial switch to protected-mode
    jc initfailed

        mov cx,1                ;get a descriptor for the 32-bit code segment
    mov ax,0
    int 31h
    jc dpmierr
    mov bx,ax
    mov dx,_text32
    mov cx,dx
    shl dx,4
    shr cx,12
    mov ax,7            ;set base
    int 31h
    or dx,-1
    xor cx,cx
    mov ax,8            ;set limit
    int 31h
    mov cx,cs
    lar cx,cx
    shr cx,8
    or  ch,40h          ;make a 32bit CS
    mov ax,9
    int 31h
    push bx
    push start32
    retf                        ;jump to 32bit CS
nohost:
        mov dx, dErr1
error:    
    mov ah, 9
    int 21h
    mov ax, 4C00h
    int 21h
nomem:
        mov dx, dErr2
    jmp error
initfailed:
        mov dx, dErr3
    jmp error
dpmierr:
        mov dx, dErr4
    jmp error

;--- the 32-bit code segment

        segment _text32 use32 public align=16 class=CODE

start32:
    mov esi, szWelcome
    call printstring
    mov ax, 4C00h       ;normal client exit
    int 21h

;--- print a string in protected-mode with simple
;--- DOS commands not using pointers.

printstring:    
    lodsb
    and al,al
    jz stringdone
    mov dl,al
    mov ah,2
    int 21h
    jmp printstring
stringdone:
        ret

        segment _data use16 public align=16 class=DATA

szWelcome db "welcome in protected-mode",CR,LF,0
dErr1 db "no DPMI host installed",CR,LF,'$'
dErr2 db "not enough DOS memory for client initialisation",CR,LF,'$'
dErr3 db "DPMI initialisation failed",CR,LF,'$'
dErr4 db "no LDT descriptors available",CR,LF,'$'

        segment stack use16 stack align=16 class=STACK
        resb 1024

group dgroup _data stack
    


OK, found this code in FreeDOS Debug ... NOT dealing with this ES, FS & GS Confused

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 19 Dec 2006, 18:14
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 19 Dec 2006, 22:06
I got my code that it is complete (for now Wink) and should work -
but doesn't.

...

EDIT: crappy code and attach kicked

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug


Last edited by DOS386 on 15 Aug 2007, 01:41; edited 1 time in total
Post 19 Dec 2006, 22:06
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.