Ich habe darüber gelesen div
und mul
Assembler-Operationen, und ich beschloss, sie in Aktion zu sehen, indem ich ein einfaches Programm in C schrieb:
Dateiaufteilung.c
#include <stdlib.h>
#include <stdio.h>
int main()
{
size_t i = 9;
size_t j = i / 5;
printf("%zu\n",j);
return 0;
}
Und dann Generieren von Assemblersprachencode mit:
gcc -S division.c -O0 -masm=intel
Aber beim Betrachten generiert division.s
Datei enthält sie keine div-Operationen! Stattdessen macht es eine Art schwarze Magie mit Bitverschiebung und magischen Zahlen. Hier ist ein Code-Snippet, das berechnet wird i/5
:
mov rax, QWORD PTR [rbp-16] ; Move i (=9) to RAX
movabs rdx, -3689348814741910323 ; Move some magic number to RDX (?)
mul rdx ; Multiply 9 by magic number
mov rax, rdx ; Take only the upper 64 bits of the result
shr rax, 2 ; Shift these bits 2 places to the right (?)
mov QWORD PTR [rbp-8], rax ; Magically, RAX contains 9/5=1 now,
; so we can assign it to j
Was ist denn hier los? Warum verwendet GCC überhaupt kein div? Wie generiert es diese magische Zahl und warum funktioniert alles?
gcc optimiert Divisionen durch Konstanten, versuchen Sie Divisionen durch 2,3,4,5,6,7,8 und Sie werden höchstwahrscheinlich sehr unterschiedlichen Code für jeden Fall sehen.
– Jabberwocky
16. Dezember 2016 um 12:03 Uhr
Hinweis: Magische Zahl
-3689348814741910323
konvertiert zuCCCCCCCCCCCCCCCD
Als einuint64_t
oder gerade ungefähr (2^64)*4/5.– chux – Wiedereinsetzung von Monica
16. Dezember 2016 um 12:17 Uhr
@qiubit: Der Compiler generiert nicht perverserweise ineffizienten Code, nur weil die Optimierung deaktiviert ist. Eine triviale “Optimierung”, die keine Codeumordnung oder Variableneliminierung beinhaltet, wird zum Beispiel trotzdem durchgeführt. Im Wesentlichen wird eine einzelne Quellanweisung in den effizientesten Code für diese isolierte Operation übersetzt. Die Compiler-Optimierung berücksichtigt den umgebenden Code und nicht nur die einzelne Anweisung.
– Clifford
16. Dezember 2016 um 12:30 Uhr
Lesen Sie diesen großartigen Artikel: Arbeit der Teilung
– Narr
16. Dezember 2016 um 12:32 Uhr
Einige Compiler tatsächlich Wille Generieren Sie perverserweise ineffizienten Code, weil die Optimierung deaktiviert ist. Sie tun dies insbesondere, um das Debuggen zu vereinfachen, wie z. B. die Möglichkeit, Haltepunkte für einzelne Codezeilen zu setzen. GCC ist in der Tat ziemlich ungewöhnlich, da es keinen echten “Keine Optimierungen”-Modus hat, weil viele seiner Optimierungen konstitutiv eingeschaltet sind. Dies ist ein Beispiel dafür, wo Sie das mit GCC sehen können. Clang hingegen und MSVC, Wille emittieren ein
div
Unterricht bei-O0
. (cc@clifford)– Cody Grey
♦
16. Dezember 2016 um 15:02 Uhr