[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

    { Executes a real mode software interrupt

    Exactly the interrupt call to get the DOS version.

    get DOS version Int 21h / function 30h
    Input:
            AH = $30
            AL = $1
    Return:
            AL = major version number
            AH = minor version number
    }

    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

    { This example shows the difference between protected and real mode
    interrupts; it redirects the protected mode handler to an own handler
    which returns an impossible function result and calls it afterwards.
    Then the real mode handler is called directly, to show the difference
    between the two.

    Used Interrupt:
    get DOS version Int 21h / function 30h
         Input: AH = $30
                AL = $1
         Return: AL = major version number
                 AH = minor version number
    }

    uses
            crt,
            go32;

    var
            r : trealregs;
            { temporary variable used for the protected mode int call }
            axreg : Word;

            oldint21h : tseginfo;
            newint21h : tseginfo;

    { this is our int 21h protected mode interupt handler. It catches
    the function call to get the DOS version, all other int 21h calls
    are redirected to the old handler; it is written in assembly
    because the old handler can't be called with pascal }
    procedure int21h_handler; assembler;
    asm
            cmpw $0x3001, %ax
            jne .LCallOld
            movw $0x3112, %ax
            iret

    .LCallOld:
            ljmp %cs:oldint21h
    end;

    { a small helper procedure, which waits for a keypress }
    procedure resume;
    begin
            Writeln;
            Write('-- press any key to resume --'); readkey;
            gotoxy(1, wherey); clreol;
    end;

    begin
            { see the text messages for further detail }
            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.