[Previous][Up][Next] Reference for unit 'go32' (#rtl)

Executing software interrupts

Simply execute a realintr() call with the desired interrupt number and the supplied register data structure. But some of these interrupts require you to supply them a pointer to a buffer where they can store data to or obtain data from in memory. These interrupts are real mode functions and so they only can access the first Mb of linear address space, not FPC's data segment. For this reason FPC supplies a pre-initialized dos memory location within the GO32 unit. This buffer is internally used for dos functions too and so it's contents may change when calling other procedures. It's size can be obtained with tb_size and it's linear address via transfer_buffer. Another way is to allocate a completely new dos memory area via the global_dos_alloc function for your use and supply its real mode address.

See also

tb_size

  

Return DOS transfer memory buffer size

transfer_buffer

  

Return offset of DOS transfer buffer

global_dos_alloc

  

Allocate DOS real mode memory

global_dos_free

  

Free DOS memory block

realintr

  

Simulate interrupt

Example

uses
        go32;

var
        r : trealregs;

begin
        r.ah := $30;
        r.al := $01;
        realintr($21, r);
        Writeln('DOS v', r.al,'.',r.ah, ' detected');
end.

Example

uses
        crt,
        go32;

var
        r : trealregs;
        axreg : Word;

        oldint21h : tseginfo;
        newint21h : tseginfo;
procedure int21h_handler; assembler;
asm
        cmpw $0x3001, %ax
        jne .LCallOld
        movw $0x3112, %ax
        iret

.LCallOld:
        ljmp %cs:oldint21h
end;

procedure resume;
begin
        Writeln;
        Write('-- press any key to resume --'); readkey;
        gotoxy(1, wherey); clreol;
end;

begin
        clrscr;
        Writeln('Executing real mode interrupt');
        resume;
        r.ah := $30; r.al := $01;  realintr($21, r);
        Writeln('DOS v', r.al,'.',r.ah, ' detected');
        resume;
        Writeln('Executing protected mode interrupt without our own',
                ' handler');
        Writeln;
        asm
                movb $0x30, %ah
                movb $0x01, %al
                int $0x21
                movw %ax, axreg
        end;
        Writeln('DOS v', r.al,'.',r.ah, ' detected');
        resume;
        Writeln('As you can see the DPMI hosts default protected mode',
                'handler');
        Writeln('simply redirects it to the real mode handler');
        resume;
        Writeln('Now exchanging the protected mode interrupt with our ',
                'own handler');
        resume;

        newint21h.offset := @int21h_handler;
        newint21h.segment := get_cs;
        get_pm_interrupt($21, oldint21h);
        set_pm_interrupt($21, newint21h);

        Writeln('Executing real mode interrupt again');
        resume;
        r.ah := $30; r.al := $01; realintr($21, r);
        Writeln('DOS v', r.al,'.',r.ah, ' detected');
        Writeln;
        Writeln('See, it didn''t change in any way.');
        resume;
        Writeln('Now calling protected mode interrupt');
        resume;
        asm
                movb $0x30, %ah
                movb $0x01, %al
                int $0x21
                movw %ax, axreg
        end;
        Writeln('DOS v', lo(axreg),'.',hi(axreg), ' detected');
        Writeln;
        Writeln('Now you can see that there''s a distinction between ',
                'the two ways of calling interrupts...');
        set_pm_interrupt($21, oldint21h);
end.

Documentation generated on: Nov 14 2015