[fpc-devel]Calling previous INTroutine

startx startx at geocities.com
Mon Dec 18 15:39:49 CET 2000


Aleksey V. Vaneev wrote:
> Okay. I've tried to use ds_alias.. Somebody said me it is a right way of 
> restoring selectors.
I do not know anything about ds_alias, but for it to work there are two
requirements to be satisfied:

	1) It should reside in the CS segment, and the compiler should remember
	about that, as you declare it as

	var
          ds_alias: Word; external name '___v2prt0_ds_alias';

	... and you refer to it with

          mov ax, cs:[ds_alias]

	I think, however, this is true, as would be no reason to declare such
	a variable with another thing in mind. If it is declared in the DS 		
segment, you can't access it without having DS correctly set up.

	2) This variable should be already locked, as you don't lock it.

I've just tried this ds_alias, and it seems to me that ds_alias resides
in DS segment itself. So, you can't use it from an interrupt procedure
if you don't lock it; moreover, you can't access it without having DS
correctly set up.

When using this mechanism, you have no need to use "procedure dsdummy",
as you don't even refer it, and so you don't have to use the small
assembler routine to set up dsdummy:

>         {asm
>                 mov ax, ds
>                 mov ebx, offset dsdummy
>                 mov cs:[ebx], ax
>         end;} // this part traps on "mov ax, ds"

About this fragment, which uses CS as imposition: this is the first
thing I tried some time ago. And, yes, this caused an error. This is
strange, because in the FPC documentation it is stated that "the code
segment is writeable by default".
Apart from that, the error you should receive is on "mov cs:[ebx],ax",
because there cannot be any error on "mov ax,ds"; this could be some
strange thing from your debugger (don't trust any). I verified it just
now using gdbpas.

Jonas Maebe wrote:
> I just looked again at this and this is wrong: this should be
> mov word ptr cs:[ebx],ax

Writing "word ptr" is not required, as the AX register is a 16 bit
register. And it does not work because it raise a SIGABORT error. I
remember that, some time ago, I tried also to set write privileges in
the code segment, but the only way to get the work done was to use "mov
[ebx],ax".

Anyway, this is your program working after some adjustment:


Assured to work.

Cheers.
-------------- next part --------------
uses Go32;

{$asmmode intel}

const
        TimerIRQVector = 8;

var
        OldIRQHandler: TSegInfo;
        ds_alias: Word; external name '___v2prt0_ds_alias';

procedure dsdummy; assembler;
asm
        dw 0
end;

procedure TimerIRQHandler; assembler;
asm
        pushad
        push es
        push ds
        push fs
        push gs

        mov  ebx,offset dsdummy
        mov  ax,cs:[ebx]
        mov ds, ax
        mov es, ax

        pushfd
        lcall [OldIRQHandler]

        pop gs
        pop fs
        pop ds
        pop es
        popad

        iret
end;

function setNewIRQHandler: Boolean;
var
        HandlerAddress: TSegInfo;

begin
        HandlerAddress.segment := get_cs;
        HandlerAddress.offset := @TimerIRQHandler;

        SetNewIrqHandler := set_pm_interrupt (TimerIRQVector, HandlerAddress);
end;

procedure lockVariables;
begin
        lock_data (OldIRQHandler, SizeOf (OldIRQHandler));
        lock_code (@dsdummy, 400);
end;

procedure unlockVariables;
begin
        unlock_data (OldIRQHandler, SizeOf (OldIRQHandler));
        unlock_code (@TimerIRQHandler, 400);
end;

var
        SaveExitProc: Pointer;

procedure TimerSafeExit;
begin
        ExitProc := SaveExitProc;

        set_pm_interrupt (TimerIRQVector, OldIRQHandler);

        unlockVariables;
end;

var
  prova	: word;

begin

        if (not get_pm_interrupt (TimerIRQVector, OldIRQHandler)) then
                halt;

        lockVariables;

        asm
                mov ax, ds
                mov ebx, offset dsdummy
                mov [ebx], ax
        end;  // this part traps on "mov ax, ds"


        if (not setNewIRQHandler) then
                begin
                        unlockVariables;
                        halt;
                end;
        SaveExitProc := ExitProc;
        ExitProc := @TimerSafeExit;

		writeln('now timer is ',memw[$40:$6c]);
        ReadLn;
		writeln('and now it is ',memw[$40:$6c]);
end.


More information about the fpc-devel mailing list