From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,1dca1cee347390dd X-Google-Attributes: gid103376,public From: "Jerry van Dijk" Subject: Re: DOS interrupts with GNAT 3.04 Date: 1996/12/25 Message-ID: <01bbf242$ea2558a0$LocalHost@jerryware> X-Deja-AN: 205887823 references: <1996Dec23.124409.5432@news> <59p725$ff4@top.mitre.org> organization: *JerryWare HQ*, Haarlem, Holland newsgroups: comp.lang.ada Date: 1996-12-25T00:00:00+00:00 List-Id: > procedure interrupt_16 (interrupt: interrupts; > register: in out dos16bit.registers_16) is > reg: registers; As DJ and other warned several times: 1) This 16-bit Borland interface supports only a limited number of DOS calls, which ones is not documented. 2) BIOS and other interrupt calls are not possible 3) These functions are *unsupported* and will disappear in the next DJGPP distribution. Here's an example that shows some reliable techniques to access DOS from the GNAT/DJGPP enviroment: -- Demonstrates how to call a dos interrupt with GNAT 3.05 with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; procedure Demo is -- Raised if the conventional memory transfer buffer is too small Transfer_Buffer_Too_Small : exception; -- Defines the DPMI available processor registers. -- Note: one of several possible definitions type Dpmi_Regs is record Di : Unsigned_16; Di_Hi : Unsigned_16; Si : Unsigned_16; Si_Hi : Unsigned_16; Bp : Unsigned_16; Bp_Hi : Unsigned_16; Res : Unsigned_16; Res_Hi : Unsigned_16; Bx : Unsigned_16; Bx_Hi : Unsigned_16; Dx : Unsigned_16; Dx_Hi : Unsigned_16; Cx : Unsigned_16; Cx_Hi : Unsigned_16; Ax : Unsigned_16; Ax_Hi : Unsigned_16; Flags : Unsigned_16; Es : Unsigned_16; Ds : Unsigned_16; Fs : Unsigned_16; Gs : Unsigned_16; Ip : Unsigned_16; Cs : Unsigned_16; Sp : Unsigned_16; Ss : Unsigned_16; end record; pragma Convention (C, Dpmi_Regs); -- Make DPMI issue a real mode interrupt procedure Dpmi_Int (Vector : in Unsigned_16; Regs : in out Dpmi_Regs); pragma Import (C, Dpmi_Int, "__dpmi_int"); -- Defines the dos extender info block type Go32_Info_Block is record Size_Of_This_Structure_In_Bytes : Unsigned_32; Linear_Address_Of_Primary_Screen : Unsigned_32; Linear_Address_Of_Secondary_Screen : Unsigned_32; Linear_Address_Of_Transfer_Buffer : Unsigned_32; Size_Of_Transfer_Buffer : Unsigned_32; Pid : Unsigned_32; Master_Interrupt_Controller_Base : Unsigned_8; Slave_Interrupt_Controller_Base : Unsigned_8; Selector_For_Linear_Memory : Unsigned_16; Linear_Address_Of_Stub_Info_Structure : Unsigned_32; Linear_Address_Of_Original_Psp : Unsigned_32; Run_Mode : Unsigned_16; Run_Mode_Info : Unsigned_16; end record; pragma Convention (C, Go32_Info_Block); -- Make the current extender info available within Ada Current_Info : Go32_Info_Block; pragma Import (C, Current_Info, "_go32_info_block"); -- Procedure to copy data to conventional memory procedure Dosmemput (Buffer : in char_array; Length : in Unsigned_32; Fysical : in Unsigned_32); pragma Import (C, Dosmemput, "dosmemput"); procedure DOS_Print(Str : in String) is -- The DOS formatted string (note the zero) DOS_String : char_array(0..Str'Length); -- The processor registers Regs : Dpmi_Regs; begin -- Translate the string to a DOS string by appending -- the '$' that DOS uses to mark the end of the string for I in Str'Range loop DOS_String (size_t (I-1)) := To_C ( Str (I)); end loop; DOS_String (size_t (Str'Length)) := To_C ('$'); -- Check that the djgpp conventional memory transfer buffer is -- large enough to hold our string. If not, raise an exception. -- Normally we would either enlarge the transfer buffer or allocate -- our own. Here we leave this as an exercise for the reader :-) if Current_Info.Linear_Address_Of_Transfer_Buffer < Str'Length + 1 then raise Transfer_Buffer_Too_Small; end if; -- Next, copy our string to the transfer buffer Dosmemput (DOS_String, Str'Length + 1, Current_Info.Linear_Address_Of_Transfer_Buffer); -- Now, tell dos to print the contents of the transfer buffer Regs.Ax := 16#0900#; -- Make Ds point to the segment part of the physical address Regs.Ds := Unsigned_16( Shift_Right( Current_Info.Linear_Address_Of_Transfer_Buffer, 4)) and 16#FFFF#; -- Make Dx point to the offset part of the physical address Regs.Dx := Unsigned_16( Current_Info.Linear_Address_Of_Transfer_Buffer) and 16#0F#; -- Issue the interrupt Dpmi_Int (16#21#, Regs); end DOS_Print; begin DOS_Print("Hello, world!"); end Demo; Jerry.