Ich denke doch, dass die unterschiedlichen Laufzeiten ihre Ursache im Code Alignment haben.
Die Ausführungsgeschwindigkeiten hängen nämlich (zumindest indirekt, s.u.) vom Offset der zu testenden Procedure ab.
Die Werte stammen aus dem weiter oben von mir modifizierten Listing. Die Ausführungsgeschwindigkeiten beziehen sich immer auf die test1-procedure:
Code: Alles auswählen
Offset i386sx16 i486dx100
h0F8 56 1397
h0F9 62 1290
h0FA 59 1290
h0FB 58 1397
h0FC 56 1397
h0FD 62 1397
h0FE 59 1397
h0FF 58 1397
h100 56 1397
h101 62 1397
h102 59 1397
h103 58 1397
h104 56 1397
h105 62 1397
h106 59 1397
h107 58 1397
h108 56 1397
h109 62 1290
h10A 59 1290
h10B 58 1397
Daraus ergibt sich meines Erachtens folgendes:
1.
Ursache der unterschiedlichen Laufzeiten ein und derselben Routine auf demselben PC ist das Code Alignment. Denn die Laufzeiten stehen in direkter Relation zu den Startoffsets der procedure, wie sich aus der Tabelle ergibt.
Irrelevant ist auch, ob und ggf. wieviele andere Procedures vorher oder nachher definiert sind (getestet!). Maßgeblich für die Auführungsgeschwindigkeit ist beim 386sx16 immer das MODULO 4 aus dem Offset der zu testenden Procedure, beim 486dx100 das MODULO 16. Bei identischen Moduli wiederholen sich die Ausführungsgeschwindigkeiten cpu-spezifisch.
2.
Dass die beste Ausführungsgeschwindigkeit nicht bei einem MODULO X=0 erzielt wird ist auch leicht erkärbar. Maßgeblich im engeren Sinn ist nämlich gar nicht der Startoffset der Procedure, da diese ja auch nur 56-62 bzw. 1290-1397 Mal in der Sekunde aufgerufen wird. Maßgeblich ist vielmehr der innere Loop der zu testenden procedure test1, der ja stets 65536 Mal pro Procedureaufruf erfolgt. Pro Sekunde sind das also 56-62 * 65536 (386sx16) bzw. 1290-1397 * 65536 Schleifendurchläufe. Es wäre also darauf zu achten, dass das Loop-Label der zu testenden Procedure code aligned wäre.
An welchem Offset die procedure selbst beginnt, ist also nur mittelbar bedeutsam, weil dies Einfluss auf das Loop-Label, das pro Aufruf 65536 Mal angesprungen wird, hat. (Bei meinem 386sx z.B. ist wohl ein Offset mit Modulo 4 = 1 ideal für das spätere Alignment der Loop-Schleife.)
3.
Hinsichtlich des Code-Alignments müßte man also "nur" darauf achten, dass die Schleifen aligned sind. Das halte ich aber für ein Ding der Unmöglichkeit: Wegen der unterschiedlichen Länge der Befehle müßte man auch das Alignment des aktuellen Befehls auf die nachfolgenden Befehle innerhalb der Schleife untersuchen. Je länger die Schleife, umso unmöglicher...
Außerdem verhält sich da wohl jeder Prozessor unterschiedlich. Während der 386sx16 sein bestes Alignment im konkreten Anwendungsfall bei Offset mod 16=9 hat, hat der 486dx hier sein worst-case-Szenario. Viel Spaß, wenn man auch noch den Pentium berücksichtigen will.
4.
Nicht, dass mir jetzt jemand drein redet

: Über das Ergebnis bin ich nämlich ziemlich froh. Ich bin eh kein Freund von Zyklen- oder Befehls(längen) zählen. Jetzt kann ich also wieder und weiter munter drauf los programmieren, ohne mir Gedanken über Befehlsoptimierungen zu machen. Hauptsache für mich ist eh' immer, dass mein code läuft, was ich schwer genug finde.
5.
Erstaunlich fand ich allerdings schon, dass der 386sx offensichtlich ein Alignment MODULO 4 bevorzugt, obwohl er sich die Befehle ja über einen 16-bit-Bus holen muss. Selbiges gilt für den 486dx, der offensichtlich auf Paragraphenausrichtung aus ist (trotz nur 32-bittigen Busses). Die Sache ist wohl noch viel komplizierter als befürchtet...
Edit: Leider verhauts mir immer das Layout in der Tabelle; der zweistellige Betrag ist die Zahl der Durchläufe auf dem 386sx, der vierstellige der vom 486dx100