www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1994/11/23/11:19:50

To: Travis Kuhn <trav AT clark DOT edu>
Cc: djgpp AT sun DOT soe DOT clarkson DOT edu
Subject: Re: Interrupts
Date: Wed, 23 Nov 94 13:35:54 +0200
From: "Eli Zaretskii" <eliz AT is DOT elta DOT co DOT il>

> If I need to call an interrupt that expects a segment:offset pair to be 
> in the registers, how do I do that in DJGPP?  Here's the things that I've 
[....]
> 4. Put the segment offset pair in _go32_dpmi_registers and call 
> _go32_dpmi_simulate_int.

# 4 is the way to go.  Your problem must be the values of ES and DI.
The answer to your next question, viz: how do I compute them? is "It
depends..."  It depends on what address do you want to pass to the
interrupt you invoke (you didn't say which function of which interrupt
you are using).  In any case, ES:DI should point to an address in
the *lower* (i.e. under 1 MByte) memory, because the interrupt gets
serviced by a real-mode routine.  If ES:DI is an address of a buffer
(like a filename in DOS I/O functions), then you must either use the
4KB-long transfer buffer provided by go32, or allocate a buffer in
conventional memory and use it.  To move data between that buffer and
your program, you must use dosmemget()/dosmemput() or movedata() (the
latter is faster when you have large buffers), or functions declared
and explained on <sys/farptr.h> include file, if you only have to move
a byte, an int, or a long.

Here is how you get the address of the low-memory buffer:

  If you use the go32 transfer buffer:

        _go32_dpmi_registers regs;

	dos_buf_addr =
            _go32_info_block.linear_address_of_transfer_buffer & 0x000fffff;
        regs.x.es = (dos_buf_addr >> 4);
        regs.x.di = dos_buf_addr & 0x0000000f;

  If you allocate your own buffer:

        _go32_dpmi_seginfo info;

        info.size = 2 * required_size / 16; /* should be in paragraphs */
        if (_go32_dpmi_allocate_dos_memory(&info))
          fail;

        dos_buf_addr = ((u_int)info.rm_segment << 4) & 0x000fffff;
        regs.x.es = (dos_buf_addr >> 4);
        regs.x.di = dos_buf_addr & 0x0000000f;

If you want to pass an address of your routine to the interrupt, to
be called as callback, you should allocate a wrapper function and
pass the address the allocating function returns in ES:DI; see the
various _go32_dpmi_allocate_real_mode_callback_XXX routines in the
libcref.info file.

Remember to zero-out the SS, SP and FLAGS fields of the _go32_dpmi_registers
structure before you call _go32_dpmi_simulate_int(), or your machine
might crash...

The int86() functions require go32 to know and support the
interrupt you are calling, and it doesn't know about all of them.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019