Recent

Author Topic: Need help with Inline 'asm byte' code from Turbo Pascal  (Read 4205 times)

Scalare

  • Newbie
  • Posts: 2
Need help with Inline 'asm byte' code from Turbo Pascal
« on: January 22, 2017, 01:01:16 am »
Hello! Let me first introduce me :). I actually started programming many years ago with Turbo Pascal, I believe it was with the computer club at my high school, that would be 1994 or something. And right now I still have some little programs lying around that I wrote around the period of 1996 until 2000, most of them written in Turbo pascal, Borland pascal or delphi.

Right now i'm trying to compile a little game I made back in those days for a 386 or 486 machine in DOS. It uses 2 pascal libraries that I didn't make, namely load_gif.pas (to load a GIF) and games.pas (to get around the 'default' keyboard handler that pauses after your first keypress and doesn't allow multiple keys being pressed at once, which is essential for games). One of the differences between freepascal and turbo pascal is that inline statements work differently. The unit 'games.pas' uses some of it, which I think should be able to be converted to use just 'asm' statements. But since I don't know much about assembler I couldn't really properly get around it.

This is the section that I need to convert.

Code: Pascal  [Select][+][-]
  1. procedure sti;
  2. inline($fb);    { STI: set interrupt flag }
  3.  
  4. procedure cli;
  5. inline($fa);    { CLI: clear interrupt flag -- not used }
  6.  
  7. procedure calloldint(sub: pointer);
  8.  
  9. { calls old interrupt routine so that your programs don't deprive the computer
  10.   of any vital functions -- kudos to Stephen O'Brien and "Turbo Pascal 6.0:
  11.   The Complete Reference" for including this inline code on page 407 }
  12.  
  13. begin
  14.   inline($9c/           { PUSHF }
  15.          $ff/$5e/$06)   { CALL DWORD PTR [BP+6] }
  16. end;
  17.  
  18.  

which gets used in a number of places.
Code: [Select]
procedure newkbdint; interrupt;   { new keyboard handler }
begin
  keydown[port[$60] mod 128] := (port[$60] < 128);  { key is down if value of
                                                      60h is less than 128 --
                                                      record current status }
  if port[$60] < 128 then wasdown[port[$60]] := true; { update WASDOWN if the
                                                        key is currently
                                                        depressed }
  calloldint(oldkbdint);                              { call old interrupt }
  mem[$0040:$001a] := mem[$0040:$001c];   { Clear keyboard buffer: the buffer
                                            is a ring buffer, where the com-
                                            puter keeps track of the location
                                            of the next character in the buffer
                                            end the final character in the
                                            buffer.  To clear the buffer, set
                                            the two equal to each other. }
  sti
end;

procedure initnewkeyint;      { set new keyboard interrupt }
var keycnt: byte;
begin
  for keycnt := 0 to 127 do begin   { reset arrays to all "False" }
    keydown[keycnt] := false;
    wasdown[keycnt] := false
    end;
  getintvec($09, oldkbdint);        { record location of old keyboard int }
  setintvec($09, addr(newkbdint));  { this line installs the new interrupt }
  sti
end;

procedure setoldkeyint;           { reset old interrupt }
begin
  setintvec($09, oldkbdint);
  sti
end;

Could you please help me with these, and how to call them from these functions?
This is what I came up with myself, would that work?

Code: [Select]
procedure sti;
begin;
asm
sti
    { STI: set interrupt flag }
end;
end;

procedure cli;
begin;
asm
cli
end;
    { CLI: clear interrupt flag -- not used }
end;

procedure calloldint(sub: pointer);

{ calls old interrupt routine so that your programs don't deprive the computer
  of any vital functions -- kudos to Stephen O'Brien and "Turbo Pascal 6.0:
  The Complete Reference" for including this inline code on page 407 }

begin
  asm
  pushf
  call dword ptr [ebp+6]
  end;
 
          { PUSHF }
     { CALL DWORD PTR [BP+6] }
end;

I added the entire source base as attachments. Keep in mind that I think I made this in 1998 so the code is kinda archaic and lame ;).

wildfire

  • Full Member
  • ***
  • Posts: 109
Re: Need help with Inline 'asm byte' code from Turbo Pascal
« Reply #1 on: January 22, 2017, 01:21:29 am »
CPU Architecture and Operating Systems have move a long way since that code was written, I strongly suspect you won't be able to convert it due to new ::) security restrictions.

A complete rewrite using modern code would be better.
A halo is a mere circle, when does it end?

Scalare

  • Newbie
  • Posts: 2
Re: Need help with Inline 'asm byte' code from Turbo Pascal
« Reply #2 on: January 22, 2017, 01:24:54 am »
I'm sorry that I wasn't more clear, my compile targets are for DOS on a 386 or 486 so the game can be run in dosbox. So that would get around much of the restrictions if that is properly emulated, right?

wildfire

  • Full Member
  • ***
  • Posts: 109
Re: Need help with Inline 'asm byte' code from Turbo Pascal
« Reply #3 on: January 22, 2017, 01:26:48 am »
Thanks for the clarification, yes if that's your target then there shouldn't be a problem, check the FPC Docs for usage of inline.

http://www.freepascal.org/docs-html/3.0.0/prog/progch3.html
« Last Edit: January 22, 2017, 01:28:46 am by wildfire »
A halo is a mere circle, when does it end?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11453
  • FPC developer.
Re: Need help with Inline 'asm byte' code from Turbo Pascal
« Reply #4 on: January 22, 2017, 02:45:30 pm »
Cli and sti are like putting

Code: Pascal  [Select][+][-]
  1. asm cli end;

everywhere where it is used. Your way is ok, but the compiler will not inline that, so will always emit a call to your cli and sti procedure.

Afaik (and most of my dos knowledge is pre 2000) interrupts work differently on the 32-bit go32v2 target because of the dos extender.

The msdos 16-bit target is new in 3..0, and theoretically you should be able  to replace it with

Code: Pascal  [Select][+][-]
  1. procedure calloldint;nostackframe;
  2. asm
  3.   db $9c,$ff,$5e,$06
  4. end;
  5.  
or even

Code: Pascal  [Select][+][-]
  1. procedure calloldint;nostackframe;
  2. asm
  3.    PUSHF
  4.    CALL DWORD PTR [BP+6]
  5. end;

but I have no practical detail knowledge about this target. In nearly all cases you need to understand what the code does to port it.


 

TinyPortal © 2005-2018