Recent

Author Topic: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU  (Read 8458 times)

Rick314

  • New Member
  • *
  • Posts: 28
Help!  The attached test program compiles and runs fine using Turbo Pascal 6.0 within DOSBox on a 2012 Dell XPS 8300 Windows 7  PC with an Intel Core i7-2600 64-bit CPU.  The 80386 assembly code in the program is a small part of a much bigger program with other assembly code procedures in it.  WITHOUT CHANGING THE ASSEMBLY CODE I want to compile and run it on the same hardware using Free Pascal Compiler and not using DOSBox.  What compiler switches and (hopefully minimal) changes to the source code are required?

Other details: Expected output is included in the comments near the end of the file.  I wrote the original program I am working on in 1992 and have done very little with x86 assembly since then.  I am new to Free Pascal but have lots of experience with Turbo Pascal 6.0.  I have recently been able to compile and run over 80 old TP 6.0 programs using Free Pascal with the -Mtp (Turbo Pascal 7.0 compatibility) switch.  Now I am trying to get old assembly code to work on new hardware with a new compiler (FPC).  (The attachment should be TEST1.PAS, but this Pascal forum won't allow .PAS attachments.  Sigh.)

Leledumbo

  • Hero Member
  • *****
  • Posts: 8112
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #1 on: February 23, 2015, 06:51:51 am »
The problem is mostly (if not all) unrecognized opcode. Looks like you have to use db/dd/dw to generate the opcode by hand (as already been used in some places in the source) as the assembler reader doesn't know the opcode.

Rick314

  • New Member
  • *
  • Posts: 28
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #2 on: February 23, 2015, 07:03:33 am »
... Looks like you have to use db/dd/dw to generate the opcode by hand (as already been used in some places in the source) as the assembler reader doesn't know the opcode.
This is explained in the code as required due to Turbo Pascal 6.0 limitations (quote below).  But if Free Pascal can properly read 80286 assembler code then it should work on a 80386-compatible CPU. So my original question remains, but more specifically I want Free Pascal to understand 80286 assembly and use the backward-compatibility features of modern 64-bit CPUs to emulate it.  Here is the code quote:

"This procedure requires an 80386 processor, as it makes use of 32-bit data operations for increased speed.  The Turbo PASCAL version 6.0 built-in assembler does not support these 386-only instructions, however. This is handled by including a "DB $66" instruction prefix byte before instructions meant to use 32-bit 386-only registers."
« Last Edit: February 23, 2015, 07:05:27 am by Rick314 »

Leledumbo

  • Hero Member
  • *****
  • Posts: 8112
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #3 on: February 23, 2015, 07:23:00 am »
But if Free Pascal can properly read 80286 assembler code then it should work on a 80386-compatible CPU. So my original question remains, but more specifically I want Free Pascal to understand 80286 assembly and use the backward-compatibility features of modern 64-bit CPUs to emulate it.
Since FPC minimum requirement is 386, I don't think the assembler reader is implemented with 80286 opcode.

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 670
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #4 on: February 23, 2015, 08:35:21 am »
The problem is that your assembler code is written for 16 bit real mode, while FPC for i386 platforms targets 32 bit protected mode. This requires a completely different way to deal with pointers, and e.g. the les/lds instructions won't work at all anymore (not in the way you are using them anyway). Another issue is that since the cpu is in 32 bit mode, "db $66" followed by an instruction using 16 bit registers would result in two "db $66" prefixes (one inserted by the db, and another by the compiler to tell the cpu that it should interpret the next instruction as a 16 bit instead of as a 32 bit instruction). There are probably more problems.

You'll have to rewrite the assembler code completely, either into Pascal or into 32 bit assembler.

Rick314

  • New Member
  • *
  • Posts: 28
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #5 on: February 23, 2015, 07:11:36 pm »
Thank you for your helpful replies.  I am looking into FPC assembly support and updating all the 80286 assembly code in my original program.

Rick314

  • New Member
  • *
  • Posts: 28
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #6 on: February 28, 2015, 06:20:24 am »
I am having a hard time getting started with Free Pascal and 80386 assembly language, after reading what I can find about both subjects.  In the way of an example for future readers like me, could someone please convert the 7-line for loop in the attached test program to assembly?  I need to see an example of accessing variables declared in Free Pascal and using pointers.

Instructions: Change the name of the attached program from .txt to .pas.  Compile it and run the program to verify you get the output shown in the comments.  Change "{ $DEFINE ASSEMBLY }" to {$DEFINE ASSEMBLY}, put assembly code at "ASSEMBLY GOES HERE" to do the same as the for loop, and post the new file.  Thank you!

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #7 on: February 28, 2015, 08:40:17 am »
If you pass -a to the compiler you get the assembly file for your Pascal source. Changing it to -al would instruct the compiler to include the source code lines as well. To get Intel dialect I requested using Microsoft Assembler using -Amasm. These options are mentioned here.

The compiler calls fpc_mod_qword and fpc_div_qword from unit system. To be able to call them, I reintroduced them at the top with corrected param order.

To deal with 64-bit variables like: Div64 : UInt64 in 32-bit assembly, I added its two halfs as two variables:
Code: [Select]
var
..
   Div64L : UInt32;
   Div64H : UInt32;
   Div64  : UInt64 absolute Div64L;
notice how Div64 covers the same address space as its halves by using absolute.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7505
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #8 on: February 28, 2015, 03:08:23 pm »
The core reason to do it in assembler is that a 64-bit / 32-bt with a 32-bit result and remainder is faster. Note that the result MUST fit in 32-bit though. Just pasting the compiler doesn't exploit that fact. (the same as in TP btw, but 32-bit/ 16-bit with 16 -bit result and rem)

An intrinsic for that option (or, slightly less optimal, a math.divmod with 64/32/32 options) would maybe ease the need for using assembler .

So I did a quick conversion. I'm by no means an assembler wizard. The whole function is optimized for the current calling convention (so wholly assembler, not just a block that loads from local variables)

I used pretty much most of the techniques Engkin describes btw.
« Last Edit: February 28, 2015, 03:23:17 pm by marcov »

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7505
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #9 on: February 28, 2015, 03:33:59 pm »
Note that       xor eax,eax                         // result of shl-32      
can be deleted.

I attached a variant that uses stosd/losd for comparison with the old version.

IIRC those instructions generally aren't faster without rep anymore though.

Rick314

  • New Member
  • *
  • Posts: 28
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #10 on: February 28, 2015, 07:35:05 pm »
Thank you for your help -- I have just what I want and realize I could have done better with the problem statement.

I forgot to mention I modified my fpc.cfg file with "-Mtp" for Turbo Pascal compatibility and you had to discover that.  Also sorry I didn't make it clear I wanted the "lodsd, div ebx, stosd" fast loop at the heart of the procedure.  This was shown in TEST1.TXT in my first post of the thread (modified with "db $66" opcodes as required in Turbo Pascal 6.0), and is in marcov's test_div2.txt.  That speed gain is the main motivation for going to assembly.  In TEST1.TXT I added comments justifying coding it 16 times inline to reduce the impact of the branch instruction, gaining another 20% speed improvement.  This procedure is part of an "approximate e (2.718...) to 1,000,000 decimal places" program with most time spent doing those 3 assembly language instructions.  I should have said all that, and thanks again.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7505
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #11 on: February 28, 2015, 08:09:01 pm »
I forgot to mention I modified my fpc.cfg file with "-Mtp" for Turbo Pascal compatibility and you had to discover that. 

Don't worry. You learn about such things after almost 17 years of FPC :-)

Quote
Also sorry I didn't make it clear I wanted the "lodsd, div ebx, stosd" fast loop at the heart of the procedure. 

Be careful. As said lodsd/stosd USED to be the fast way. However starting with Pentium-I, optimization rules changed. Be sure to benchmark my original vs my -2 to make sure that it is actually faster.


Rick314

  • New Member
  • *
  • Posts: 28
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #12 on: February 28, 2015, 09:44:58 pm »
I attached a variant that uses stosd/losd for comparison with the old version.
IIRC those instructions generally aren't faster without rep anymore though.

Be careful. As said lodsd/stosd USED to be the fast way. However starting with Pentium-I, optimization rules changed. Be sure to benchmark my original vs my -2 to make sure that it is actually faster.
Please clarify what you meant by "...generally aren't faster without rep anymore though."  (rep?)

I will benchmark both versions.  Thanks again for your help.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7505
Re: Turbo Pascal 6.0, 80386 assembly language, Free Pascal, 64-bit CPU
« Reply #13 on: February 28, 2015, 10:36:27 pm »
Please clarify what you meant by "...generally aren't faster without rep anymore though."  (rep?)

I mean that afaik lods<x> and stos<x> use without the "rep;" prefix is generally discouraged out of
performance considerations for processors after the 486.

There are (rare) exceptions though, specially in some AMD processors, where some combinations with short opcodes avoids a decoding bottleneck.