Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2000-12

Calling previous INTroutine

12 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Aleksey V. Vaneev

Hello,

I've encountered a problem with calling previous interrupt routine in my handler. I'm doing this under go32v2. I install handler with set_pm_interrupt(), and before that I do get_pm_interrupt(). Everything works, but when I chain previous handler using the following construct:

  asm
    pushfd
    call qword ptr [OldHandler]
  end;
  It just traps. What can I do? (I'm working with system timer ISR).

Best regards,
Aleksey

Jonas Maebe
Show quoted text 12 lines
I've encountered a problem with calling previous interrupt routine in my handler. I'm doing this under go32v2. I install handler with set_pm_interrupt(), and before that I do get_pm_interrupt(). Everything works, but when I chain previous handler using the following construct: asm pushfd call qword ptr [OldHandler] end; It just traps. What can I do? (I'm working with system timer ISR).

Make sure OldHandler is locked in memory using lockdata(). And shouldn't you use 'call far ptr [OldHandler]' instead?

Jonas

Aleksey V. Vaneev

Hello,

Show quoted text 10 lines
> following construct: > > asm > pushfd > call qword ptr [OldHandler] > end; > > It just traps. What can I do? (I'm working with system timer ISR). Make sure OldHandler is locked in memory using lockdata(). And shouldn't you use 'call far ptr [OldHandler]' instead?

It says that compiler ignores "far". But it doesn't work anyways. Locked or not. Maybe there's some undocumented mechanism to do ISR chaining in go32v2?

Best regards,
Aleksey

Jonas Maebe
Show quoted text 12 lines
>> asm >> pushfd >> call qword ptr [OldHandler] >> end; >> >> It just traps. What can I do? (I'm working with system timer ISR). >Make sure OldHandler is locked in memory using lockdata(). And shouldn't >you use 'call far ptr [OldHandler]' instead? It says that compiler ignores "far". But it doesn't work anyways. Locked or not. Maybe there's some undocumented mechanism to do ISR chaining in go32v2?

Note that ds probably doesn't point to the data segment of your program when the ISR is entered, so you should either put the oldhandler variable in the code segment (and do a "call far ptr [cs:oldhandler]"), or first load ds with the ds from the program (it's shown how to do this in the ISR example of the go32v2 docs) before executing the above call.

BTW: "call qword ptr" should be rejected, because far pointers are only 48bit, not 64bit.

Jonas

Aleksey V. Vaneev

Hello,

Show quoted text 16 lines
>>> asm >>> pushfd >>> call qword ptr [OldHandler] >>> end; >>> >>> It just traps. What can I do? (I'm working with system timer ISR). >>Make sure OldHandler is locked in memory using lockdata(). And shouldn't >>you use 'call far ptr [OldHandler]' instead? >It says that compiler ignores "far". But it doesn't work anyways. >Locked or not. Maybe there's some undocumented mechanism to do ISR >chaining in go32v2? Note that ds probably doesn't point to the data segment of your program when the ISR is entered, so you should either put the oldhandler variable in the code segment (and do a "call far ptr [cs:oldhandler]"), or first load ds with the ds from the program (it's shown how to do this in the ISR example of the go32v2 docs) before executing the above call.

As I said, ISR by itself (of course, DS and ES are correct) performs well. But chaining doesn't works.

Yes, I can ban that system ISR, but CRT unit doesn't work this way (it needs system timer). And it is generally invalid to stop system timer from running. So, I don't know what to do now.

Show quoted text 6 lines
BTW: "call qword ptr" should be rejected, because far pointers are only 48bit, not 64bit. Jonas

Best regards,
Aleksey

startx
to Aleksey V. Vaneev: I've encountered a problem with calling previous interrupt routine in my handler. I'm…
Aleksey V. Vaneev wrote
I've encountered a problem with calling previous interrupt routine in my handler. I'm doing this under go32v2. I install handler with

This works well for me, try:

// ------------ start of interrupt code
procedure datasegment; assembler;
asm
  dw 0
end;

Procedure IRQ0_Service;
begin
asm
pusha
push ds
push es
push esi
push edi
mov ebx,offset datasegment
mov ax,cs:[ebx] // read right DS from code
mov ds,ax
mov es,ax

  end;
	// do whatever you want here
  // call old handler if needed
  Inc(IRQ0_OldCount,IRQ0_Counter);
  if IRQ0_OldCount<IRQ0_Counter then begin	// overflow
    asm
      pushf
      lcall [Oldint08]
    end
  end else Port[$20] := $20;
  // exit code
  asm
    pop  edi
    pop  esi
    pop  es
    pop  ds
    popa
    leave
    iret
  end

end;

procedure Int00End;
begin
end;
  // later... setting up things
  asm
    mov  ax,ds
    mov  ebx,offset datasegment
    mov  word ptr [ebx],ax
  end;
  // all data must be locked. Below I lock a contiguous area of vars
  lock_data(DATA_Buffer,longint(@EndDSInt)-longint(@DATA_Buffer));
  // lock all used code (the old handler has not to be locked)
  lock_code(@DataSegment,longint(@Int00End)-longint(@DataSegment));
  Get_pm_interrupt(8,OldInt08);
  Disable;
  myinterr.segment := get_cs;
  myinterr.offset  := @Irq0_Service;
  set_pm_interrupt(8,myinterr);
  // reprogram the counter
  Port[$43] := $36;     // command to set new count
  Port[$40] := Lo(IRQ0_Counter);	// a new value
  Port[$40] := Hi(IRQ0_Counter);
  Port[$43] := 0;
  Enable;

Regards.

_________________________________________________________ Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com

Aleksey V. Vaneev

Hello fpc-devel,

> I've encountered a problem with calling previous interrupt routine > in my handler. I'm doing this under go32v2. I install handler with This works well for me, try:

Okay. I've tried to use ds_alias.. Somebody said me it is a right way of restoring selectors. And, BTW, somehow my code traps with "access violation" when I'm doing "mov ax, ds"... (btw, my computer is i486dx-100).

Here's what I've got:

It still TRAPS...

---------------------------
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 ax, cs:[ds_alias]
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;
        Result := set_pm_interrupt (TimerIRQVector, HandlerAddress);
end;
procedure lockVariables;
begin
        lock_data (OldIRQHandler, SizeOf (OldIRQHandler));
        lock_code (@TimerIRQHandler, 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;
begin
        if (not get_pm_interrupt (TimerIRQVector, OldIRQHandler)) then
                halt;
        lockVariables;
        {asm
                mov ax, ds
                mov ebx, offset dsdummy
                mov cs:[ebx], ax
        end;} // this part traps on "mov ax, ds"
        if (not setNewIRQHandler) then
                begin
                        unlockVariables;
                        halt;
                end;
        SaveExitProc := ExitProc;
        ExitProc := @TimerSafeExit;
        WriteLn ('Timer running...');
        ReadLn;
end.
---------------------------

Best regards,
Aleksey

Jonas Maebe
procedure datasegment; assembler; asm dw 0 end;

[cut]

Show quoted text 10 lines
procedure Int00End; begin end; // later... setting up things asm mov ax,ds mov ebx,offset datasegment mov word ptr [ebx],ax

I just looked again at this and this is wrong: this should be

mov word ptr cs:[ebx],ax

(although using the ds alias stuff already solved this problem for you)

Jonas

startx
to Aleksey V. Vaneev: Okay. I've tried to use ds_alias.. Somebody said me it is a right way of restoring…
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:

Show quoted text 5 lines
{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.

Ingmar Tulva
to startx
startx wrote 10 lines
> {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".

Hello, I just happened to read it and... Can a code selector be writeable at all?! I just like recall that it can be either execute-only or read-and-execute. Or have I got something wrong (whitch is quite possible, I've only read PM basics but never hacked in sutch a low level)?

Ingmar tulva,

startx
to Ingmar Tulva
Ingmar Tulva wrote 13 lines
On Mon, 18 Dec 2000, startx wrote: > > {asm > > mov ax, ds > > mov ebx, offset dsdummy > > mov cs:[ebx], ax > > end;} // this part traps on "mov ax, ds" > Hello, I just happened to read it and... Can a code selector be writeable at all?! I just like recall that it can be either execute-only or read-and-execute. Or have I got something wrong (whitch is quite possible, I've only read PM basics but never hacked in sutch a low level)?

Clearly, I don't know whether a code selector can be written to. Probably not. That fragment comes right from a fpc example, which was not tested I think...

It seems to work, indeed, if you use the same displacement/offset, but inside the data segment.

_________________________________________________________ Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com

Thomas Schatzl
to startx

Subject: Re: [fpc-devel]Calling previous INTroutine

Show quoted text 11 lines
Ingmar Tulva wrote: > > On Mon, 18 Dec 2000, startx wrote: > > > > {asm > > > mov ax, ds > > > mov ebx, offset dsdummy > > > mov cs:[ebx], ax > > > end;} // this part traps on "mov ax, ds" > > > Hello, I just happened to read it and... Can a code selector be

writeable

> at all?! I just like recall that it can be either execute-only or > read-and-execute. Or have I got something wrong (whitch is quite > possible, I've only read PM basics but never hacked in sutch a low

level)?

Clearly, I don't know whether a code selector can be written to.

It depends on some attributes set. It's possible but not implemented.

Probably not. That fragment comes right from a fpc example, which was not tested I think...

All examples from the go32 unit documentation (and I guess as well the others) at least worked with _some_ version of the fpc compiler (e.g. compiles and runs). It is sometimes hard to keep up to date in that respect especially if somebody use the official version and others already work with snapshots. Sometimes internal things just change without me taking notice.... (well, at least for people like me not so involved with compiler development).
Btw, the examples of the recent go32 docs (don't know whether 'snapshots' are regulary made) have been updated to work fine with FPC 1.00 about three months ago. For example they don't use any code segment quirks anymore (e.g. storing djgpp_ds_alias using some awkward assembly code in code segment) because there are cleaner ways to accomplish that.

Also the note about that the code segment selector can be written to has certainly been removed too since I can't find this one anymore.

Please update your documentation (the go32 unit description part), for the examples have changed a little in that respect. I guess not only this part was updated btw.

It seems to work, indeed, if you use the same displacement/offset, but inside the data segment.

Both the cs and ds selector map the same memory area. The only difference is that cs and ds have different access rights. The memory allocation algorithm always makes sure that they always map the same memory area.

Note that internal variables like ___v2prt0_ds_alias are not automatically locked at program startup, I admit I missed that for some reason. So this variable is not locked in the current example.

Btw, for every example in the go32 docs there is one available with comments inside the code. They were skipped in the printable version due to size constraints and for better readability. Please get the CVS doc sources if you want/need them.

Regards,
Thomas