From NISC.SRI.COM!unix!Teknowledge.COM!uw-beaver!zephyr.ens.tek.com!tektronix!reed!reeder Mon Jan 29 03:59:26 PST 1990 Article 583 of comp.binaries.apple2: Path: NISC.SRI.COM!unix!Teknowledge.COM!uw-beaver!zephyr.ens.tek.com!tektronix!reed!reeder >From: reeder@reed.bitnet (Doug Reeder,box 722,Mac 306,7771551,) Newsgroups: comp.binaries.apple2 Subject: Dhrystone source code Message-ID: <13979@reed.UUCP> Date: 26 Jan 90 18:35:36 GMT Sender: news@reed.UUCP Reply-To: reeder@reed.bitnet (Doug Reeder) Organization: Institute of Knowledge, Jinx Lines: 843 This is the source to Dhrystone, the original program from which Dhryhack was hacked up. This program will give you real dhrystone numbers which you can compare with any other published dhrystone numbers. Dhryhack just has all the pointer and record bits chopped out. (* **************************************************************************** * * "DHRYSTONE" Benchmark Program * ----------------------------- * * Version: Pascal, Version 2.1 * * File: dhry.p * * Date: May 17, 1988 * * Author: Reinhold P. Weicker * Siemens AG, E STE 35 * Postfach 3240 * 8520 Erlangen * Germany (West) * Phone: [xxx-49]-9131-7-20330 * (8-17 Central European Time) * Usenet: ..!mcvax!unido!estevax!weicker * * Original Version (in Ada) published in * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), * pp. 1013 - 1030, together with the statistics * on which the distribution of statements etc. is based, * * This version uses calls to the Pascal runtime library of the * Berkeley UNIX system (4.3 bsd) for time measurement. * For measurements on other systems, these calls need to be * modified. * * Collection of Results: * Reinhold Weicker (address see above) and * * Rick Richardson * PC Research. Inc. * 94 Apple Orchard Drive * Tinton Falls, NJ 07724 * Phone: (201) 834-1378 (9-17 EST) * Usenet: ...!seismo!uunet!pcrat!rick * * Please send results to Rick Richardson and/or Reinhold Weicker. * Complete information should be given on hardware and software used. * Hardware information includes: Machine type, CPU, type and size * of caches; for microprocessors: clock frequency, memory speed * (number of wait states). * Software information includes: Compiler (and runtime library) * manufacturer and version, compilation switches, OS version. * The Operating System version may give an indication about the * compiler; Dhrystone itself performs no OS calls in the measurement loop. * * The complete output generated by the program should be mailed * such that at least some checks for correctness can be made. * **************************************************************************** * * History: This version Pascal/2.1 has been made for two reasons: * * 1) There is a need for a common Pascal version of * Dhrystone. Although translation from the published (Ada) * version to Pascal is straightforward in most aspects, * there are cases where it may not be obvious to everyone. * There should be, as far as possible, only one Pascal version * of Dhrystone such that results can be compared without * restrictions. Also, a Pascal version of Dhrystone has not yet * found a network distribution comparable to the C version * (version 1.1) distributed by Rick Richardson. * * 2) As far as it is possible without changes to the Dhrystone * statistics, optimizing compilers should be prevented from * removing significant statements. * * This Pascal version 2.1 has been made consistent with the * C version 2.1; therefore the acknowledgments for the C version * are due for the Pascal version as well: I thank * Rick Richardson (Tinton Falls, NJ), Chaim Benedelac (Nat. * Semi.), David Ditzel (SUN), Earl Killian and John Mashey (MIPS), * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) * for their help with comments on earlier versions of the * benchmark. * * Changes: In the initialization part, this version differs * from the Pascal version previously distributed by Reinhold * Weicker, the number of runs through Dhrystone is obtained * interactively from the terminal. Output of the result * has been changed to conform to the C version (2.1). * The changes in the initialization part and in the printing * of the result have no impact on performance measurement * since they are outside the measaurement loop. * * Inside the measurement loop, this version follows the * version previously distributed by Reinhold Weicker. * As a correction to the published version, a statement * initializing Array2Glob [8,7] (outside the measurement * loop) has been added. Otherwise, this array element would * have an undefined value. * * At several places in the benchmark, code has been added, * but within the measurement loop only in branches that * are not executed. The intention is that optimizing compilers * should be prevented from moving code out of the measurement * loop, or from removing code altogether. Since the statements * that are executed within the measurement loop have NOT been * changed, all numbers defining the "Dhrystone distribution" * (distribution of statements, operand types and locality) * still hold. Except for sophisticated optimizing compilers, * execution times for this version should be the same as * for previous versions. * * Since it has proven difficult to subtract the time for the * measurement loop overhead in a correct way, the loop check * has been made a part of the benchmark. This does have * an impact - though a very minor one - on the distribution * statistics which have been updated for this version. * * All changes within the measurement loop are described * and discussed in the companion paper "Rationale for * Dhrystone version 2". * * Because of the self-imposed limitation that the order and * distribution of the executed statements should not be * changed, there are still cases where optimizing compilers * may not generate code for some statements. To a certain * degree, this is unavoidable for small synthetic benchmarks. * Users of the benchmark are advised to check code listings * whether code is generated for all statements of Dhrystone. * * Version 2.1 is identical to version 2.0 distributed via * the UNIX network Usenet in March 1988 except that it corrects * some minor deficiencies that were found by users of version 2.0. * None of these affected execution times. * The following corrections have been made: * - The expected result for PointerGlob^.EnumComp was corrected * - Brackets are used in the computation of DhrystonesPerSecond * *************************************************************************** * * Compilation model and measurement (IMPORTANT): * * This program contains the Dhrystone program, including measurement setup, * in one file. The original (Ada) program contained three packages, * - a package with global type definitions, * - Pack_1, containing the main program (Proc_0 in Ada) and procedures * Proc_1, ... , Proc_5, * - Pack_2, containing Proc_6, ... , Proc_8, Func_1, ..., Func_3. * Since ISO/ANSI Standard Pascal provides no means to express separate * compilation (although many Pascal implementations provide such a feature), * it is not possible to formulate a portable Pascal version with the program * in several modules, corresponding more closely to the Ada and C versions. * Therefore, no attempt has been made to construct a Pascal version with * the program consisting of several modules. * * This difference may impact execution time because the compiler can * perform more data flow analysis for a single-module program; * sophisticated compilers may be able to suppress code generation for * some parts of the program. * Users should check machine code listings generated by the compiler * to ensure that code is generated for all parts of the program. * * The following "ground rules" apply for measurements: * - No procedure merging * - Otherwise, compiler optimizations are allowed but should be indicated * See the companion paper "Rationale for Dhrystone Version 2" for a more * detailed discussion of these ground rules. * * For 16-Bit processors (e.g. 80x86), times for all compilation models * ("small", "medium", "large") should be given if possible, together * with a definition of these models for the compiler system used. * ************************************************************************** * * Dhrystone (Pascal version) statistics: * * [Comment from the first distribution by Reinhold Weicker, * the distribution statistics have been updated for Version 2.1. * Note that because of language differences, the numbers are different * from the Ada version. The main difference is that the variables that * are local variables of "Proc_0" (Ada) or "main" (C) are global * variables in the Pascal version.] * * The following program contains statements of a high level programming * language (here: Pascal) in a distribution considered representative: * * assignments 58 * control statements 28 * procedure, function calls 15 * * 100 statements are dynamically executed. The program is balanced with * respect to the three aspects: * * - statement type * - operand type (for simple data types) * - operand access * operand global, local, parameter, or constant. * There is no static nesting of blocks or procedures, * therefore all variables are either global or local. * * The combination of these three aspects is balanced only approximately. * * 1. Statement Type: * ----------------- number * * V1 := V2 15 * V := Constant 12 * (incl. V1 := F(..) * Assignment, 7 * with array element * Assignment, 6 * with record component * -- * 40 40 * * X := Y +|-|and|or Z 5 * X := Y +|-|"=" Constant 6 * X := X +|- 1 3 * X := Y *|/ Z 2 * X := Expression, 1 * two operators * X := Expression, 1 * three operators * -- * 18 18 * * if .... then .... 14 * with "else" 7 * without "else" 7 * executed 3 * not executed 4 * for I in 1..N do ... 7 | counted every time * while ... do ... 4 | the loop condition * repeat ... until 1 | is evaluated * case ... end 1 * with 1 * -- * 28 28 * * P (...) procedure call 10 * X := F (...) * function call 5 * -- * 15 15 * --- * 101 * * 22 of the 58 assignments have a variable of a constrained * (sub-)type as their destination. In general, discriminant checks * will be necessary in these cases; however, the compiler may * optimize out some of these checks. * * The average number of parameters in procedure or function calls * is 1.80 (not counting the function values as implicit parameters). * * * 2. Operators * ------------ * number approximate * percentage * * Arithmetic 27 52.9 * * + 16 31.4 * - 7 13.7 * * 3 5.9 * div 1 2.0 * * Comparison 20 39.2 * * = 9 17.6 * <> 4 7.8 * > 1 2.0 * < 3 5.9 * >= 1 2.0 * <= 2 3.9 * * Logic 4 7.8 * * AND 1 2.0 * OR 1 2.0 * NOT 2 3.9 * * -- ----- * 51 99.9 * * * 3. Operand Type (counted once per operand reference): * --------------- * number approximate * percentage * * Integer 135 54.7 % * Character 47 19.0 % * Enumeration 31 12.6 % * Boolean 13 5.3 % * Pointer 11 4.5 % * String30 6 2.4 % * Array 2 0.8 % * Record 2 0.8 % * --- ------- * 247 100.1 % * * When there is an access path leading to the final operand (e.g. a record * component), only the final data type on the access path is counted. * * There are 16 accesses to components of a record, 9 of them go to * a component in a variant part. For some of these accesses, the * compiler may suppress generation of code checking the tag field * during optimization. * * * 3. Operand Locality: * ------------------- * * local variable 84 34.0 % * global variable 58 23.5 % * parameter 45 18.2 % * value 23 9.3 % * reference 22 8.9 % * function result 5 2.0 % * constant 55 22.3 % * --- ------- * 247 100.0 % * * * The program does not compute anything meaningful, but it is syntactically * and semantically correct. All variables have a value assigned to them * before they are used as a source operand. * * There may be cases where a highly optimizing compiler may recognize * unnecessary statements and may not generate code for them. * * There has been no explicit effort to account for the effects of a * cache, or to balance the use of long or short displacements for code or * data. * **************************************************************************** *) program Dhrystone (input, output); (***************) const (* for measurement *) MicrosecondsPerClock = 1000; ClocksPerSecond = 1000; (* In Berkeley UNIX Pascal, the function "clock" *) (* returns milliseconds *) TooSmallTime = 2000; (* Measurements should last at least 2 seconds *) type (* Global type definitions *) Enumeration = (Ident1, Ident2, Ident3, Ident4, Ident5); OneToThirty = 1..30; OneToFifty = 1..50; CapitalLetter = 'A'..'Z'; String30 = packed array [OneToThirty] of char; Array1DimInteger = array [OneToFifty] of integer; Array2DimInteger = array [OneToFifty, OneToFifty] of integer; RecordPointer = ^RecordType; RecordType = record PointerComp: RecordPointer; case Discr: Enumeration of Ident1: (* only this variant is used, *) (* but in some cases discriminant *) (* checks are necessary *) (EnumComp: Enumeration; IntComp: OneToFifty; StringComp: String30); Ident2: (Enum2Comp: Enumeration; String2Comp: String30); Ident3, Ident4, Ident5: (Char1Comp, Char2Comp: char); end; (* record *) var (* Ada version: Variables local in Proc_0 *) Int1Glob, Int2Glob, Int3Glob: OneToFifty; CharIndex: char; EnumGlob: Enumeration; String1Glob, String2Glob: String30; (* Ada version: Variables global in Pack_1 *) PointerGlob, NextPointerGlob: RecordPointer; IntGlob: integer; BoolGlob: boolean; Char1Glob, Char2Glob: char; Array1Glob: Array1DimInteger; Array2Glob: Array2DimInteger; (* Variables for measurement *) RunIndex, NumberOfRuns, BeginClock, EndClock, SumClocks: integer; Microseconds, DhrystonesPerSecond: real; I: integer; (* end of variables for measurement *) procedure Proc1 ( PointerParVal: RecordPointer); forward; procedure Proc2 (var IntParRef: OneToFifty); forward; procedure Proc3 (var PointerParRef: RecordPointer); forward; procedure Proc4; forward; (* without parameters *) procedure Proc5; forward; (* without parameters *) procedure Proc6 ( EnumParVal: Enumeration; var EnumParRef: Enumeration); forward; procedure Proc7 ( Int1ParVal, Int2ParVal: OneToFifty; var IntParRef: OneToFifty); forward; procedure Proc8 (var Array1ParRef: Array1DimInteger; var Array2ParRef: Array2DimInteger; Int1ParVal, Int2ParVal: integer); forward; function Func1 ( Char1ParVal, Char2ParVal: CapitalLetter): Enumeration; forward; function Func2 (var String1ParRef, String2ParRef: String30): boolean; forward; function Func3 ( EnumParVal: Enumeration): boolean; forward; procedure Proc1; (* (PointerParVal: RecordPointer) *) (* executed once *) begin with PointerParVal^.PointerComp^ (* = PointerGlobNext *) do begin PointerParVal^.PointerComp^ := PointerGlob^; PointerParVal^.IntComp := 5; IntComp := PointerParVal^.IntComp; PointerComp := PointerParVal^.PointerComp; Proc3 (PointerComp); (* PointerParVal^.PointerComp^.PointerComp = PointerGlob^.PointerComp *) if Discr = Ident1 then (* executed *) begin IntComp := 6; Proc6 (PointerParVal^.EnumComp, EnumComp); PointerComp := PointerGlob^.PointerComp; Proc7 (IntComp, 10, IntComp); end (* then *) else (* not executed *) PointerParVal^ := PointerParVal^.PointerComp^; end; (* with *) end; (* Proc1 *) procedure Proc2; (* (var IntParRef: OneToFifty) *) (* executed once *) (* InParRef = 3, becomes 7 *) var IntLoc: OneToFifty; EnumLoc: Enumeration; begin IntLoc := IntParRef + 10; repeat (* executed once *) if Char1Glob = 'A' then (* executed *) begin IntLoc := IntLoc - 1; IntParRef := IntLoc - IntGlob; EnumLoc := Ident1; end (* if *) until EnumLoc = Ident1; (* true *) end; (* Proc2 *) procedure Proc3; (* (var PointerParRef: RecordPointer) *) (* executed once *) (* PointerParRef becomes PointerGlob *) begin if PointerGlob <> nil then (* executed *) PointerParRef := PointerGlob^.PointerComp else (* not executed *) IntGlob := 100; Proc7 (10, IntGlob, PointerGlob^.IntComp); end; (* Proc3 *) procedure Proc4; (* without parameters *) (* executed once *) var BoolLoc: boolean; begin BoolLoc := Char1Glob = 'A'; BoolGlob := BoolLoc or BoolGlob; Char2Glob := 'B'; end; (* Proc4 *) procedure Proc5; (* without parameters *) (* executed once *) begin Char1Glob := 'A'; BoolGlob := false; end; (* Proc5 *) procedure Proc6; (* ( EnumParVal: Enumeration; var EnumParRef: Enumeration) *) (* executed once *) (* EnumParVal = Ident3, EnumParRef becomes Ident2 *) begin EnumParRef := EnumParVal; if not Func3 (EnumParVal) then (* not executed *) EnumParRef := Ident4; case EnumParVal of Ident1: EnumParRef := Ident1; Ident2: if IntGlob > 100 then EnumParRef := Ident1 else EnumParRef := Ident4; Ident3: EnumParRef := Ident2; (* executed *) Ident4: ; Ident5: EnumParRef := Ident3; end; (* case *) end; (* Proc6 *) procedure Proc7; (* ( Int1ParVal, Int2ParVal: OneToFifty; var IntParRef: OneToFifty) *) (* executed three times *) (* first call: Int1ParVal = 2, Int2ParVal = 3, *) (* IntParRef becomes 7 *) (* second call: Int1ParVal = 10, Int2ParVal = 5, *) (* IntParRef becomes 17 *) (* third call: Int1ParVal = 6, Int2ParVal = 10, *) (* IntParRef becomes 18 *) var IntLoc: OneToFifty; begin IntLoc := Int1ParVal + 2; IntParRef := Int2ParVal + IntLoc; end; (* Proc7 *) procedure Proc8; (* (var Array1ParRef: Array1DimInteger; var Array2ParRef: Array2DimInteger; Int1ParVal, Int2ParVal: integer) *) (* executed once *) (* Int1ParVal = 3 *) (* Int2ParVal = 7 *) var IntIndex, IntLoc: OneToFifty; begin IntLoc := Int1ParVal + 5; Array1ParRef [IntLoc] := Int2ParVal; Array1ParRef [IntLoc+1] := Array1ParRef [IntLoc]; Array1ParRef [IntLoc+30] := IntLoc; for IntIndex := IntLoc to IntLoc+1 do Array2ParRef [IntLoc, IntIndex] := IntLoc; Array2ParRef [IntLoc, IntLoc-1] := Array2ParRef [IntLoc, IntLoc-1] + 1; Array2ParRef [IntLoc+20, IntLoc] := Array1ParRef [IntLoc]; IntGlob := 5; end; (* Proc8 *) function Func1; (* (Char1ParVal, Char2ParVal: CapitalLetter): Enumeration *) (* executed three times, returns always Ident1 *) (* first call: Char1ParVal = 'H', Char2ParVal = 'R' *) (* second call: Char1ParVal = 'A', Char2ParVal = 'C' *) (* third call: Char1ParVal = 'B', Char2ParVal = 'C' *) var Char1Loc, Char2Loc: CapitalLetter; begin Char1Loc := Char1ParVal; Char2Loc := Char1Loc; if Char2Loc <> Char2ParVal then (* executed *) Func1 := Ident1 else (* not executed *) begin Char1Glob := Char1Loc; Func1 := Ident2; end; end; (* Func1 *) function Func2; (* (var String1ParRef, String2ParRef: String30): boolean *) (* executed once, returns false *) (* String1ParRef = 'DHRYSTONE PROGRAM, 1''ST STRING' *) (* String2ParRef = 'DHRYSTONE PROGRAM, 2''ND STRING' *) var IntLoc: OneToThirty; CharLoc: CapitalLetter; begin IntLoc := 2; while IntLoc <= 2 do (* loop body executed once *) if Func1 (String1ParRef[IntLoc], String2ParRef[IntLoc+1]) = Ident1 then (* executed *) begin CharLoc := 'A'; IntLoc := IntLoc + 1; end; (* if, while *) if (CharLoc >= 'W') and (CharLoc < 'Z') then (* not executed *) IntLoc := 7; if CharLoc = 'R' then (* not executed *) Func2 := true else (* executed *) begin if String1ParRef > String2ParRef then (* not executed *) begin IntLoc := IntLoc + 7; IntGlob := IntLoc; Func2 := true end else (* executed *) Func2 := false; end; (* if CharLoc *) end; (* Func2 *) function Func3; (* (EnumParVal: Enumeration): boolean *) (* executed once, returns true *) (* EnumParVal = Ident3 *) var EnumLoc: Enumeration; begin EnumLoc := EnumParVal; if EnumLoc = Ident3 then (* executed *) Func3 := true; end; (* Func3 *) begin (* main program, corresponds to procedures *) (* Main and Proc_0 in the Ada version *) (* Initializations *) new (NextPointerGlob); new (PointerGlob); PointerGlob^.PointerComp := NextPointerGlob; PointerGlob^.Discr := Ident1; PointerGlob^.EnumComp := Ident3; PointerGlob^.IntComp := 40; PointerGlob^.StringComp := 'DHRYSTONE PROGRAM, SOME STRING'; String1Glob := 'DHRYSTONE PROGRAM, 1''ST STRING'; Array2Glob [8,7] := 10; writeln; writeln ('Dhrystone Benchmark, Version 2.1 (Language: Pascal)'); writeln; writeln ('Please give the number of runs through the benchmark: '); readln (NumberOfRuns); writeln; writeln ('Execution starts, ', NumberOfRuns : 7, ' runs through Dhrystone'); BeginClock := clock; (***************) (* Start timer *) (***************) for RunIndex := 1 to NumberOfRuns do begin Proc5; Proc4; (* Char1Glob = 'A', Char2Glob = 'B', BoolGlob = false *) Int1Glob := 2; Int2Glob := 3; String2Glob := 'DHRYSTONE PROGRAM, 2''ND STRING'; EnumGlob := Ident2; BoolGlob := not Func2 (String1Glob, String2Glob); (* BoolGlob = true *) while Int1Glob < Int2Glob do (* loop body executed once *) begin Int3Glob := 5 * Int1Glob - Int2Glob; (* Int3Glob = 7 *) Proc7 (Int1Glob, Int2Glob, Int3Glob); (* Int3Glob = 7 *) Int1Glob := Int1Glob + 1; end; (* while *) (* Int1Glob = 3 *) Proc8 (Array1Glob, Array2Glob, Int1Glob, Int3Glob); (* IntGlob = 5 *) Proc1 (PointerGlob); for CharIndex := 'A' to Char2Glob do (* loop body executed twice *) if EnumGlob = Func1 (CharIndex, 'C') then (* not executed *) begin Proc6 (Ident1, EnumGlob); String2Glob := 'DHRYSTONE PROGRAM, 3''RD STRING'; Int2Glob := RunIndex; IntGlob := RunIndex; end; (* Int1Glob = 3, Int2Glob = 3, Int3Glob = 7 *) Int2Glob := Int2Glob * Int1Glob; Int1Glob := Int2Glob div Int3Glob; Int2Glob := 7 * (Int2Glob - Int3Glob) - Int1Glob; (* Int1Glob = 1, Int2Glob = 13, Int3Glob = 7 *) Proc2 (Int1Glob); (* Int1Glob = 5 *) end; (* for RunIndex *) EndClock := clock; (**************) (* Stop timer *) (**************) writeln ('Execution ends'); writeln; writeln ('Final values of the variables used in the benchmark:'); writeln; writeln ('IntGlob: ', IntGlob : 5); writeln (' should be: 5'); write ('BoolGlob: '); if BoolGlob = true then writeln ('TRUE') else writeln ('FALSE'); writeln (' should be: TRUE'); writeln ('Char1Glob: ', Char1Glob); writeln (' should be: A'); writeln ('Char2Glob: ', Char2Glob); writeln (' should be: B'); writeln ('Array1Glob [8]: ', Array1Glob [8] : 5); writeln (' should be: 7'); writeln ('Array2Glob [8,7]: ', Array2Glob [8,7] : 5); writeln (' should be: NumberOfRuns + 10'); writeln ('PointerGlob^.Discr: ', ord (PointerGlob^.Discr) : 5); writeln (' should be: 0'); writeln ('PointerGlob^.EnumComp: ', ord (PointerGlob^.EnumComp) : 5); writeln (' should be: 2'); writeln ('PointerGlob^.IntComp : ', PointerGlob^.IntComp : 5); writeln (' should be: 17'); write ('PointerGlob^.StringComp: '); for I := 1 to 30 do write (PointerGlob^.StringComp [I]); writeln; writeln (' should be: DHRYSTONE PROGRAM, SOME STRING'); writeln ('NextPointerGlob^.Discr: ', ord (NextPointerGlob^.Discr) : 5); writeln (' should be: 0'); writeln ('NextPointerGlob^.EnumComp: ', ord (NextPointerGlob^.EnumComp) : 5); writeln (' should be: 1'); writeln ('NextPointerGlob^.IntComp: ', NextPointerGlob^.IntComp : 5); writeln (' should be: 18'); write ('NextPointerGlob^.StringComp: '); for I := 1 to 30 do write (NextPointerGlob^.StringComp [I]); writeln; writeln (' should be: DHRYSTONE PROGRAM, SOME STRING'); writeln ('Int1Glob: ', Int1Glob : 5); writeln (' should be: 5'); writeln ('Int2Glob: ', Int2Glob : 5); writeln (' should be: 13'); writeln ('Int3Glob: ', Int3Glob : 5); writeln (' should be: 7'); writeln ('EnumGlob: ', ord (EnumGlob) : 5); writeln (' should be: 1'); write ('String1Glob: '); for I := 1 to 30 do write (String1Glob [I]); writeln; writeln (' should be: DHRYSTONE PROGRAM, 1''ST STRING'); write ('String2Glob: '); for I := 1 to 30 do write (String2Glob [I]); writeln; writeln (' should be: DHRYSTONE PROGRAM, 2''ND STRING'); writeln; writeln; SumClocks := EndClock - BeginClock; if SumClocks < TooSmallTime then begin writeln ('Measured time too small to obtain meaningful results'); writeln ('Please increase number of runs'); writeln; end else begin Microseconds := SumClocks * MicrosecondsPerClock / NumberOfRuns; DhrystonesPerSecond := NumberOfRuns * ClocksPerSecond / SumClocks; write ('Microseconds for one run through Dhrystone: '); writeln (Microseconds : 8 : 1); write ('Dhrystones per Second: '); writeln (DhrystonesPerSecond : 8 : 1); writeln; end; end.