© J R Stockton, ≥ 2008-03-19

Borland Delphi Programming

Links within this site :-

I got Delphi 3 standard edition in Autumn 1998. Between 2006-10-14 and 2008-01-12, I could not run Delphi 3. On 2008-02-10, I added Delphi 2006.

THIS PAGE WAS LARGELY WRITTEN WHEN I HAD ONLY DELPHI 3.

Differences in Language, TP/BP/Delphi

The core languages are rather similar, but as the implementations are very distinct, buggy programs may behave differently. This can be useful in development.

The TP/BP ~65520 byte limit on the size of a structure does not apply in D3; the limit may be $40000000.

String handling is different, and there are several types of string. See "PChars and strings" by Rudy Velthuis, via Home or TeamB Weblog.

It appears that, in D3, Writeln evaluates all its arguments before printing any, whereas BP7 evaluates and prints each in turn. Try the program.

begin Writeln(' Test ', sqrt(-1), ' that!') end.

in each language. The cause, I am told, is that Delphi flushes the buffer only at the end of the line.

Default lengths for types vary - be careful here. No Delphi set occupies 3 bytes. In Delphi, variables in records are by default not packed; for compatibility between versions, use packed and consider variable sizes.

Procedure/Function parameter passing differs : check assembler sections.

In console program invocation parameter lists, '"' (#34) is a normal character in TP/BP, but acts as a bracket in Delphi & TMT.

In low-level code optimisation, that which is best in Delphi is not necessarily that which was best in BP/TP.

BP7 to Delphi

Conversion

An administratively simple Turbo Pascal program can often be converted with little difficulty to a Delphi console mode program running in a Windows-32 MS-DOS box; a single conditionalised source may be practical for both Pascal and Delphi. One can use the Delphi 3 Command-Line Compiler.

A program with a non-trivial human interface (including Turbo Vision) will need considerable redesign to become a Delphi Windows-GUI program, though data-crunching parts may be more or less unaffected.

Replacement Units

On EFD Systems tools page (now at archive.org) : "Crt_EFD is a Delphi32 console mode reproduction of the DOS text mode features found in the Crt unit from Turbo Pascal v7.0. Freeware with source code."

Pasquale Morvillo has written PASW32, a freeware/shareware BP-compatible RTL for 32-bit Delphi (untested); alas, it unzips to SETUP.EXE, and there is no information on what SETUP does (can one uninstall? What changes does it make? Check the licence conditions first). Also :-

http://www.simtel.net/pub/simtelnet/win95/delphi/w32pas21.zip
ftp://ftp.simtel.net/pub/simtelnet/win95/delphi/w32pas21.zip 307303 bytes
w32pas21.zip    CRT, DOS, WINCRT, WINDOS unit for Delphi. Free

Equivalent Functions

Some 16-bit BP7 library functions do not have similarly-named equivalents in 32-bit Delphi 3; the following incipient Table may help to locate what can be used instead.

PascalDelphi
Any type type~type Ttype ?
Assign=AssignFile (better)
Close=CloseFile (better)
Delay~Sleep (Win32 API?)
DiskFree
DiskSize
~ Those exist, but max results too small
What is better?
Exec~WinExec, ShellExecute, CreateProcess
FExpand~ExpandFileName
GetDate
GetTime
=Date + DecodeDate
Time + DecodeTime
GetEnv*GetEnvironmentVariable (Win32 API)
file attribute constants =precede with 'fa'
MemAvail*See TMemoryStatus in SYSTEM.PAS ??
ReadKey*various Win32 API calls
PrefixSeg-Not available
Ptr(Seg, Ofs)-None - flat 32-bit
SetDate + SetTime= SetSystemTime (Win32 API?)
or SetLocalTime (API?)
Sptr-gone
TextRec=TTextRec (Two "T"s)
Val=Val, StrToFloat

* : This seems OK :-

const PXC : string [9] = 'PRNTXCMD'#0 ;
var J : integer ; St : string ;
begin
  {$IFDEF Pascal} Dec(PXC[0]) ; St := GetEnv(PXC) ;
  {$ELSE Delphi}
  J := GetEnvironmentVariable(@PXC[1], @St[1], 255) ;
  St[0] := char(byte(J)) ;
  {$ENDIF}

* : The following (if visible) have been offered, but are untested :-


Command-Line Compiler DCC32

With Delphi 3, at a DOS prompt in Windows 98 and XP, DCC32 -CC file.pas generates file.exe as a console-mode program, provided that only straightforward Pascal is used. Unit references and routines may need attention.

Compiling with DCC32 (D2+ ?) can be a useful check for a BP7 program, since it gives hints and warnings which BP7 does not. It may also be a useful stage in conversion to a GUI program.

The following programs/units in my Web programs/ directory, among others, have been compiled (some need version.pas, and/or conditionals set) and run thus (with D3), although they mostly have not been greatly tested in Delphi :-

mjd_date.pas, dateprox.pas, longcalc.pas, cheklinx.pas, lagrange.pas,
jad_9514.pas, paschal.pas, powers.pas, series.pas, queens_8.pas,
wr-roman.pas, pastri.pas, fpatan2.pas, arccot.pas, invcos.pas,
countdwn.pas, permute.pas, permutes.pas, cvt_rome.pas, eratost*.pas,
baseconv.pas, hebclndr.pas, cols.pas, leapyear.pas, sixbytes.pas,
tenbytes.pas, floatval.pas

In some cases functionality may differ somewhat (and suggestions for restoring it are welcome; as are reports of tests with other Delphi); in particular, timings are generally in 55 ms units in Pascal and may be changed to 1 ms in Delphi. Note that, after changes in Pascal, the programs are not always immediately retested in Delphi.

Other programs have needed greater changes :-

listdirs.pas → dirslist.pas

Now, longcalc.pas is only a program if compiled with PROGRAM defined; otherwise it is a Unit, for use with my GUI-driven vastcalc.

The statement "{$OBJEXPORTALL ON}" may prevent DCC32, but not the IDE, making an EXE.

Date and Time

Although it was written for Pascal, a lot of Borland Pascal Time and Date may be of use to those using Delphi. There is much date/time information elsewhere on my site.

Note: In DOS, Windows, Pascal, and Delphi, date/time is generally local date/time. But UNIX is GMT-based - to get GMT/UT, use GetSystemTime.

Primoz Gabrijelcic : Time Is The Simplest Thing - The Delphi Magazine, Jan 2001.

File Date and Time

The MS-DOS structure, as shown by the DIR command, is supported.

Windows 9x introduced more detailed recording.

Win98 win32.hlp has : "The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601.". That is bad documentation. Really, "since Jan 1" should mean "starting Jan 2"; GMT is needed; and the calendar is [Proleptic] Gregorian, not then in general use. They mean :" ... 100-nanosecond intervals since Gregorian AD 1601-01-01 00:00:00 GMT.".

If necessary, a TFileTime can be handled as a compvariable.

Calendar Date/Time : TDateTime

The unit of TDateTime is one day. The stated range covers AD 0001 to 9999 inclusive, but the bounds are not (in Delphi 3) enforced in all operations; the year rolls over after 65535.

Type TDateTime is an IEEE/Pascal/Delphi Double for Local Civil Gregorian DayCount; the fractional part represents time of day. It can be used for GMT or UT. Routines Now Date Time use Local Civil Time; exact GMT equivalents are not available, but GMT can be obtained.

In a variant holding a date, there is a TDateTime and a marker of value varDate ($0007).

For compatibility with other software, Day 1 is 1899-12-31. The integer part is Date, the fractional part is Time-of-Day. The difference is 693594. Because of the way negative date numbers are treated, the numeric range seems to be all Doubles which satisfy -653594.0 < DT ≤ -1.0   or   0.0 ≤ DT < 2958466.0 The range   -1.0 < DT < 0.0   duplicates the day 1899-12-30 >00:00:00.

The origin was chosen for compatibility with other systems, in which the original intention had been to have 1900-01-01 as Day 1. But the absence of 1900 02 29 had been forgotten.

A Double has 53 significant bits, and the daycount (1989-2079) uses 16 bits. So there are currently 37 bits for Time-of-Day in a Date. With just over 16 bits for Second-of-Day, there are 23 bits to resolve a second; so the current resolution of TDateTime is of the order of half a microsecond; by test, it seems to be about that. That time will be doubled from Monday 5th June 2079.

Note that only a few times of the day can be represented exactly : 12:00, 06:00, 03:00, 01:30, 00:45, 00:22:30, 00:11:15, ... and their multiples.

There is no specific TDateTime representation of "NULL" = absent/unknown; one could make use of a NaN.

The Delphi current-instant function, Now, uses Win32 API GetLocalTime. For me, when using D3 on Win98, the resolution was on average 54.9 ms but the value returned changed in steps of 50 ms and 60 ms (cf. DOS $40:$6C, Pascal GetTime). I expect the average to be 10 ms or 15.625 ms in WinNT & WinXP systems. Function Now is atomic, i.e. midnight-safe. Obviously, Date+Time is not. I gather that the implementation of Now varies with OS version (e.g. Kylix).

Being a Double, a TDateTime has a potential range exceeding ±10308. In Delphi 3 (2+), the lowest integer value correctly interpreted by DecodeDate is -693593 = AD 0001-01-01; with lower values, it seems that Y M & D are all zeroed. For the highest safe date, and for a general discussion of Time in Delphi, including Y2k, see ItsAboutTime by Glenn Lawrence; but 231 days is about 5,880,000 years.

When forming differences of dates, one may need to Trunc each value before subtraction.

Procedure DecodeTime seems to round to the nearest millisecond.

In Delphi 1, Day 1 was AD 0001-01-01.

Extending Date Fields

Unlike JavaScript new Date(Y, M', D), Delphi EncodeDate(Y, M, D) does not allow out-of-range Month or Day; but in calculation those are often useful. For example, the last day of a month can be obtained as the zeroth of the next month. For out-of-range years, recall that the secular Gregorian Calendar repeats every 400 years which is 146097 days.

Here, EncodeYMD allows for out-of-range Y, M & D. DecodeYMD, DayInTheWeek and DecodeHMS allow for DT outside the TDateTime range.

These are now changed and tested, but insufficiently; do your own verification.

uses SysUtils ;

const NaN = 0/0 ;


// EncodeYMD. DecodeYMD :
// Input values are increased by 20000 years then brought into the safe
// range AD 2000-3999.  Borland standard functions are then used, and
// the result then compensated.

// Should be OK now for non-integer DT of either sign, agreeing
// with the corresponding Borland functions when within range.

const
Days20000Y = 7304850 ;
Days2000Y  =  730485 ;

function EncodeYMD(const Y, M, D : integer) : Double ;
var YM, YY, Z : integer ;
begin
  YY := Y + 20000 ; Z := YY div 2000 ;
  YM := (2000 + YY mod 2000)*12 + M - 1 ;
  Result := EncodeDate(YM div 12, YM mod 12 + 1, 1) + D - 1
    - Days20000Y - Days2000Y + Z*Days2000Y;
  end {EncodeYMD} ;

procedure DecodeYMD(const DT : Double ; out Y, M, D : word) ;
var X, Z : integer ;
begin X := Trunc(DT) + Days20000Y ; Z := X div Days2000Y ;
  DecodeDate(Days2000Y + X mod Days2000Y, Y, M, D) ;
  Y := Z*2000 + Y - 22000 ;
  end {DecodeYMD} ;


function DayInTheWeek1(const DT : Double) : integer ;
begin // ISO
  if DT>=0 then Result := 1 + Trunc(DT+6) mod 7
           else Result := 7 + Trunc( DT ) mod 7 ;
  end {DayInTheWeek1} ;
// or
function DayInTheWeek2(const DT : Double) : integer ;
begin // ISO
  Result := 1 + (Trunc(DT)+777777776) mod 7 ;
  end {DayInTheWeek2} ;


function DateFrac(const DT : Double) : double ;
  begin Result := Abs(Frac(DT)) end {DateFrac} ; // needed ???


procedure DecodeHMS(const DT : Double; out Hr, Mn, Sc, ms : word) ;
var Si, XX : integer ;
begin XX := Round(Abs(Frac(DT))*864e5) ; // not TRUNC
  Si := XX div 1000 ; ms := XX mod 1000 ;
  Mn := Si div   60 ; Sc := Si mod   60 ;
  Hr := Mn div   60 ; Mn := Mn mod   60 end {DecodeHMS} ;

N'th Xday of Month

function NXDM(const Nth, Xday, Month, Year : integer) : TDateTime ;
var ED : TDateTime ;
begin ED := EncodeDate(Year, Month, 1) ;
  Result := ED + (XDay + 7 - DayOfWeek(ED)) mod 7 + 7*(Nth-1) end ;
  end { NXDM } ;

UNDERTESTED. The value of the first 7 could need to be adjusted, though I think not. Note that for Nth=0 the last Xday of the previous month is obtained. The above should work for any definition of day-of-week, provided that Xday is consistent with DayOfWeek.

Negative TDateTime

The time interpretation of non-integral negative values (at least, in D3), as used in the Encode/Decode procedures with dates before Day 0, is in my view ridiculous; but was defined, I'm told, by Microsoft. Try a simple test program such as my delpdate.pas, output delpdate.txt (improved 2000-09-03, with functions to linearise the conversions). The signed integer part is the day count, while the unsigned fractional part is time-of-day. "The Delphi RTL was updated in Delphi 5 to handle negative dates correctly." At least in Delphi 3, both +0.5 and -0.5 decode to 1899-12-30 12:00:00, as can be deduced from the program results below.

uses SysUtils ;

var Q : TDateTime ; J : integer ; Y, M, D, h, n, s, c : word ;

begin Writeln('   J    Q=J/3         Decode(Q)') ;
for J := -6 to +6 do begin Q := J/3.0 ;
  DecodeDate(Q, Y, M, D) ; DecodeTime(Q, h, n, s, c) ;
  Write(Format(' %3d %8.3f %8d-%2.2d-%2.2d %2.2d:%2.2d',
    [J, Q, Y, M, D, h, n])) ;
  if J=0 then Write('  --') ;
  Writeln end ;
end.
   J    Q=J/3         Decode(Q)
  -6   -2.000     1899-12-28 00:00
  -5   -1.667     1899-12-29 16:00
  -4   -1.333     1899-12-29 08:00
  -3   -1.000     1899-12-29 00:00
  -2   -0.667     1899-12-30 16:00
  -1   -0.333     1899-12-30 08:00
   0    0.000     1899-12-30 00:00  --
   1    0.333     1899-12-30 08:00
   2    0.667     1899-12-30 16:00
   3    1.000     1899-12-31 00:00
   4    1.333     1899-12-31 08:00
   5    1.667     1899-12-31 16:00
   6    2.000     1900-01-01 00:00

2000-10-04 ff.: function ParadoxTimeToTDateTime, modified from one E-mailed to me by Jeffrey A. Wormsley, which he made from a delpdate.pas routine, now in delpdate.pas, with demo code.

.NET

I read that the .NET framework does not properly support negative TDateTime.

Calendar Date/Time : TTimeStamp

Also, TTimeStamp is a Record containing Date and Time fields, which are integers respectively of DayCount from proleptic Gregorian AD 0001-01-01 and of milliseconds from midnight.

It seems less used, but much better, than TDateTime (unless microsedond resulution is needed).

Calendar Date/Time : Miscellaneous

Date/Time Handling

For technical work, one can subtract daycounts and represent the difference by combinations of weeks, days, hours, minutes, seconds; and one can reasonably use years by dividing the days by 365.25 and accepting the slight irregularity (use 365.2425 for long intervals).

For administrative work, one needs an administrative ruling - note that the difference between 2001-01-01 and 2001-01-31 is 30 days, and looks less than a month; however, the difference between 2001-01-31 and 2001-03-01 is only 29 days, but looks over a month and possibly two.

Consider the Globals ShortDateFormat, LongDateFormat; one can do

ShortDateFormat := LongDateFormat ;

but that may not be wise.

Delphi has quite a number of routines to work with Gregorian dates. Windows localisation settings are used, but, as always, be careful with such.

Routines in my Unit DateProx

There are first-principles BP7/Delphi routines, which make no reference (* barring a test call of GetDate(...) / DecodeDate(Date, ...) *) to Pascal, Delphi, Dos, or Windows date/time facilities, for handling Gregorian, Julian, and various Civil dates, within about 32000BC to 32000AD, including ISO week number, Gregorian and Dionysian (Julian) Easter, Summer Time, ..., in my dateprox.pas, tested by mjd_date.pas. See those (in mjd_date.zip) in my programs directory.

There are also Week Number (etc.?) routines using Delphi EncodeDate DecodeDate.

The DateUtils Unit

The heading of DateUtils is reproduced at csdn (disregard the Japanese).

ISO paragraph numbers are version-dependent; the version should be stated (and current : 2004).

The ISO link needs updating (see box); the treasure-troves link is not now good.

JD (?noon) and MJD are readily converted by [En|De]codeDate.

International Standard ISO 8601 date operations are included in a unit, DateUtils, new in Delphi 6. The date format is YYYY-MM-DD, the time format is hh:mm:ss, the week is Mon=1 to Sun=7, and week 1 of a year contains the First Thursday and January 4th. Meanwhile, my own code for such work (with some from others) is in my dateprox.pas.

Always check that a date-related routine matches actual needs.

Routine WeekOfTheYear in the Delphi 7 DateUtils unit gives ISO Week Numbers from a TDateTime. (Verified; but there is a confirmed Monday error for non-integer negative input; see d=57477. Better, shorter, faster, correct code is in dateunit.zip

Some Turbo Delphi 2006 DateUtils routines are not satisfactory; see in dateunit.zip.

Date Formats

It seems that the standard routines StrToDate / StrToDateTime cannot read the dd-MMM-yy / dd-MMM-yyyy formats, although inverse routines can generate them.

Time Zones

When forming differences of times, remember the possibility of a Summer Time change; for portables, also a Time Zone change. Remember that the computer can be set for an incorrect location; and that the Windows rules may be in error, and are only intended to be the current rules anyway. GMT is available.

To convert between local TDateTime and GMT, see "TIME_ZONE_INFORMATION", etc., in Win32 Help. It includes the local rules for Summer Time, though that is an independent concept. GetTimeZoneInformation is in the Windows unit. See the program tz-check.pas, which includes demonstration calls to other Windows time routines.

To convert file times to GMT, there is available to Delphi "LocalFileTimeToFileTime (uses Windows)", and its inverse "FileTimeToLocalFileTime"; see Win32 Help.

Interval Timing

One can use Now; one can do better. Avoid Time if the span may include midnight.

Milliseconds

DWORD function GetTickCount is in the Windows unit (D3).

GetTickCount gives whole milliseconds since boot, and (in my Win98) any value can appear. But a program should NOT expect to see all values, because of multi-tasking.

As a longword or dword, GetTickCount wraps after 232 milliseconds = 49.71 days (49 days 17:02:47.296).

The following demonstrated true 1 ms resolution, in a PII/300 Win98 DOS box, compiling with D3 "DCC32 -cc"; use Ctrl-C to stop it. However, I've seen it said that GetTickCount changes at 18.2 Hz. In Windows NT, 10 ms resolution has been reported. The situation appears complex : TEST!

uses Windows ;
var A, B, N : integer ;
begin A := GetTickCount ; Writeln(A) ; N := 0 ;
  repeat B := GetTickCount ; Inc(N) ;
    if B<>A then begin Write(N:7, B-A:3) ; A := B ; N := 0 end ;
    until false ;
  end.

If treated as signed, GetTickCount rolls over after 24.85 days, which can lead to error when subtracting : "such a bug exist in TControlScrollBar".

I don't know nearly enough about the actual mechanism of GetTickCount.

CPU Cycles

Consider API QueryPerformanceFrequency(x) and QueryPerformanceCounter(x).

For using the RDTSC instruction, see rdtsc.pas. N.B. (1) it seems that, on some systems, executing the HLT instruction halts the TSC counter; (2) Power Management can affect the running or rate seen.

Delphi Time Routines

These include :-

GetTickCount() == GetCurrentTime() : ms since boot
GetSystemTime(), GetSystemTimeAsFileTime() : GMT, 2 formats
GetLocalTime(), Time : Local Time

Not in my D3 or Win98 Help, AFAICS :-

MultimediaTimers --
  mmSystem.timeGetTime(), timeGetSystemTime() -- in mm.hlp
CreateWaitableTimer() -- 98/NT/W2K

Maths and Trig

For number representation and accuracy, see Pascal Floating-Point; there is in this respect little difference between Pascal and Delphi.

Math Unit

Standard (cheaper) Delphi did not always have the Math Unit - my reduced-price UK Delphi 3 does not have it installed (but my Turbo Delphi 2006 does have it). That Delphi 3 retains the standard Pascal functions, from which all else can be built; and the Web has other sources of advanced maths functions. For the Power function, X^Y, see Pascal Maths.

On 17 Sep 1999 in news:comp.lang.pascal.delphi.misc, Earl F. Glynn <EarlGlynn@att.net> wrote that : Section A of MathInfo summarizes various facts about the math unit; alternative sources for many math functions via the Delphi Math Functions pages.

Rounding

Apparently, Delphi 6 provides easy means of altering the FPU control word, and hence of altering the meaning of the function Round. This seems dangerous.

The System unit of Delphi 3 has Set8087CW according to the Help.

SinCos

The SinCos function evaluates both Sin & Cos, rapidly.

ArcCos

In the online help for ArcTan, Delphi up to version 5 (Delphi 6 has ArcCos as such, so omits this) retains the ArcCos (InvCos, inverse cosine) error - see my Pascal Maths, invcos.pas and invcos.txt.

ArcTan2

The code for direct ATAN2, see in Code Snippets below from fpatan2.pas, may be useful for those without access to the Maths unit; see also other test programs nearby (via Pascal Maths).

In Delphi 3 (and D6, TD2006) ArcTan2 Help, it seems to me that "IN: |Y| < 2^64, |X| < 2^64, X<>0" is wrong. X=0 Y<>0 is a proper case, as is Y=0 X<>0; and I suspect that X=Y=0, which is theoretically indeterminate, reliably gives 0.0. The stated limits of 2^64 also seem unlikely.

An expert (TM) says that the FPU itself can handle all possible extended X & Y for FPATAN; so ArcTan2 should be able to do the same, in spite of what that Help says. As D3 has no Math unit, I could only test the FPU itself; my tests agree with TM. A simple general test is SPIRALS. Tests of TD2006 using MATHUNIT.ZIP confirm the above.

File Types

See "Teach Yourself Delphi 3 in 14 days" (Borland Press), ~p.143 and Index.

incomplete
Extension Purpose
.pasMain source
.intPartial source (interface)
.dcuUnit file
.dfmForm file
.dfoOption file
.dllDynamic Link Library
.dprProject
.drfTemp Win Res file
.exeExecutable
.resResource File
.~??Backup Files
....

See also Pascal Introduction for other information on file types.

Line Ends

IDE

An MS-DOS text file, such as a *.PAS file, should have CR LF ($0D $0A) at the end of each line. It appears that the Editor and Compiler disagree in their interpretation of defective line ends (just $0D, and maybe just $0A or other combinations); this can cause confusion, especially if "//" is followed by a defective end and a non-comment line. ("//" should be followed by a space, lest the code be seen by MS OE, which will prepend.)

[20041221] A fix is to pass the file through an editor which rectifies line ends, or through something based on this :-

while not EoF do begin Readln(S) ; Writeln(S) end ;

Programs

N.B. Delphi itself may be a Delphi program.

From Pascal to Delphi 5, only CR=#13 was recognised as a line ending, LF being ignored. From D6, LF=#10 is also recognised. Or similar.

General

Many tools, including MiniTrue and many editors, can be used to inspect and/or correct line ends.

Regular Expressions

RegExps are extremely useful in string handling; they can be used for parsing, format checking, for substitution, and for field extraction. They can be powerful, yet they are easy enough to use for comparatively simple tasks. They are implemented in a number of programming languages, and also in editors and editing tools such as SED and MiniTrue.

Page JavaScript RegExps & Validation introduces RegExps in a JavaScript context.

RegExp units for Delphi exist ... Untested :-

N.B. In JavaScript, which is interpreted, the code implementing RegExps is always available; thus it always worth using a RegExp if it improves the script. But in Delphi any use of a RegExp requires the inclusion of a significant part of a RegExp unit; the trade-offs are different, and RegExps should not be used trivially.

Code Snippets

Delphi snippets concerned with bit/byte-bevel operations are now in Delphi Bit/Byte-Moving. Parts of Borland Pascal Optimisation 0 ff. also apply.

After Terje Mathisen :-

function atan2(y : extended ; x : extended) : extended ;
assembler ;
asm  fld [y] ; fld [x] ; fpatan  end ;

After Robert Rossmair :-

function UMul(N, M : longint) : longint ;
{ multiply two unsigned long integers }
asm  mul edx  end ;

After Duncan Murdoch, to trigger a break :-

procedure BreakNow; assembler;
asm  int 3  end ;

After Peter Below (TeamB) :- Win32: these use Delphi 2/3 register calling convention and thus will get the first parameter in eax, the second in edx!

function PortIn(IOport : word) : byte ; assembler ;
asm  mov dx,ax ; in al,dx  end ;

function PortInW(IOport : word) : word ; assembler ;
asm  mov dx,ax ; in ax,dx  end ;

procedure PortOut(IOport : word ; Value : byte) ; assembler ;
asm  xchg ax,dx ; out dx,al  end ;

procedure PortOutW(IOport : word ; Value : word) ; assembler ;
asm  xchg ax,dx ; out dx,ax  end ;

After John Herbster :-

procedure ClearX87Exceptions { clears pending FPU exceptions } ;
asm  FNCLEX  end ;

See also remaindr for a way to speed up jobs requiring MOD & DIV of the same arguments.

For Loops

A For loop may not be able to accept a range of values greater than MaxInt, perhaps just where these are given as constant values. Optimisation can reverse the count (but only when it does not matter), causing confusion to the naive debugger user.

Debugging

As for Pascal, have all possible run-time checks on all the time, except possibly when your code is known, for sure, to be good and speed/size matters. Also compile-time "Hints and Warnings".

See "For Loops" above.

Bugs

D5 bug fixes index.

The Delphi Bug List, at one time maintained by Reinier Sterkenburg.

Delphi5 Buglist Off-line Browser (which needs Paradox). It's not clear which List it fetches.

A random sample of fact and rumour :-

Home Page
Mail: no HTML
© Dr J R Stockton, near London, UK.
All Rights Reserved.
These pages are tested mainly with Firefox and W3's Tidy.
This site, , is maintained by me.
Head.