Ooookay, das Ergebnis meiner fast forensischen, wenn auch nur ziemlich schnellen
/kurzen(?) Untersuchungen sieht wie folgt aus:
Code: Alles auswählen
Assemblierung des x86-Codes
; #FTTicks_per_Day = 864000000000
; dummy1.q = 864000000000
MOV dword [v_dummy1],711573504
MOV dword [v_dummy1+4],201
; dummy2.q = #FTTicks_per_Day
MOV dword [v_dummy2],711573504
MOV dword [v_dummy2+4],201
;
; var1 = dummy1.q / dummy2.q
PUSH dword [v_dummy1+4]
PUSH dword [v_dummy1]
LEA eax,[v_dummy2]
PUSH dword [eax+4]
PUSH dword [eax]
PUSH dword [esp+12]
PUSH dword [esp+12]
CALL Div64
MOV [esp],eax
MOV [esp+4],edx
POP eax
POP edx
MOV dword [v_var1],eax
; var2 = dummy1.q / #FTTicks_per_Day
PUSH dword [v_dummy1+4]
PUSH dword [v_dummy1]
PUSH dword 201
PUSH dword 711573504
PUSH dword [esp+12]
PUSH dword [esp+12]
CALL Div64
MOV [esp],eax
MOV [esp+4],edx
POP eax
POP edx
MOV dword [v_var2],eax
Code: Alles auswählen
Assemblierung des x86-64-Codes (x64)
; #FTTicks_per_Day = 864000000000
; dummy1.q = 864000000000
MOV rax,864000000000
MOV qword [v_dummy1],rax
; dummy2.q = #FTTicks_per_Day
MOV rax,864000000000
MOV qword [v_dummy2],rax
; var1 = dummy1.q / dummy2.q
MOV r15,qword [v_dummy1]
PUSH qword [v_dummy2]
MOV rax,r15
POP rcx
CQO
IDIV rcx
MOV r15,rax
MOV qword [v_var1],r15
; var2 = dummy1.q / #FTTicks_per_Day
MOV r15,qword [v_dummy1]
MOV rax,r15
MOV rcx,711573504
CQO
IDIV rcx
MOV r15,rax
MOV qword [v_var2],r15
Anmerkung: Nur die relevanten Ausschnitte wurden gepostet, kein vollständiger Code.
Wie unschwer zu erkennen ist, greift PB bei x86-Code auf eine externe Funktion zurück (Div64) - keine Ahnung warum und was damit erreicht wird, aber es funktioniert. Beim x64-Code sieht das anders aus (da wurde "direkt" also im IDIV dividiert), daher kann man beide nicht miteinander vergleichen.
Was allerdings beim x64-Code auffällt, ist, dass der Divisor beide Male in rcx gespeichert wird (IDIV rcx bedeutet: Ganzzahl-Division RAX / RCX), wenn man 2 Zeilen darüber schaut, lässt sich erkennen, dass bei der Division durch die Variable klarerweise der Wert der Variable in RCX gespeichert wird (PUSH dword [dummy2] {...} POP rcx). Bei der Division durch einen konstanten Wert wird RCX allerdings auf den Wert 711573504 gestellt, was garnicht funktionieren
kann. Rechnet man 864000000000 / 711573504 kommen die erwarteten 1214 raus.
Was heißt das? Das heißt, dass beim x64 4.70 Beta-Release irgendjemand die Idee hatte, bei konstanten Division den vom Programmierer festgelegten Divisor durch die Zahl 711573504 zu ersetzen. (Die Zahl bleibt von Programm zu Programm scheinbar gleich).
Ein Mysterium, welches ich nicht lösen konnte ist, dass auch in der X86-Version auf den Wert 711573504 zurückgegriffen wurde. Warum es dennoch funktioniert, kann ich nicht sagen, da ich den Code für die Prozedur 'Div64' nicht kenne. Scheinbar ist 711573504 eine Art magische Zahl, welche das Dividieren auf unterster Ebene erleichtern soll, nur wurde (falls meine Annahmen stimmen) die Zahl bei 64-Bit-Code falsch verwendet.
Also @PB-Entwickerteam: Kloppt mal ganz schnell einen Patch raus.
Edit: Außerdem ist werden im Divisionscode überflüssige Zuweisungen gemacht. Jaja, es ist nur eine Beta, aber gesagt ist gesagt.
Code: Alles auswählen
; var2 = dummy1.q / #FTTicks_per_Day
MOV r15,qword [v_dummy1]
MOV rax,r15
MOV rcx,711573504
CQO
IDIV rcx
MOV r15,rax
MOV qword [v_var2],r15
Wäre ersetzbar durch
Code: Alles auswählen
; var2 = dummy1.q / #FTTicks_per_Day
MOV rax,qword [v_dummy1]
MOV rcx,864000000000 ;Edit2: der Richtigkeit halber wurde der richtige Wert eingesetzt EndEdit2
IDIV rcx
MOV qword [v_var2],rax
CQO scheint eine Convert Quoad to O (?) Instruktion zu sein, allerdings hat das Löschen jener Instruktion bei mir keinen Unterschied gemacht.
EndEdit