Odin's Inline Assembler: Warum Assembly doch typisiert ist
Everyone says assembly is untyped—everyone is wrong
GingerBill, der Entwickler der Programmiersprache Odin, argumentiert, dass Assembly entgegen der landläufigen Meinung sehr wohl typisiert ist – jede Anweisung hat definierte Operandentypen, Registerklassen und Clobber-Effekte. Er kritisiert stringbasierte Inline-Assembler wie die von GCC und Clang als „bolted on“ und stellt Odins eigenen Inline-Assembler vor, der in nur sieben Tagen entstand. Dieser integriert sich nahtlos in die Sprache, verwendet eine einheitliche Syntax für alle ISAs, ist vollständig typgeprüft und bietet semantische Diagnosen. Ein historischer Rückblick auf MSVC und Turbo Pascal zeigt, dass bessere Ansätze existierten, aber an ISA-Grenzen scheiterten.
Assembly ist effektiv eine polyadische typisierte Algebra, bei der alle so tun, als wäre sie eine Suppe aus Bytes.
- amluto
Ich habe sehr gemischte Meinungen zur benutzerdefinierten Syntax. Meiner Meinung nach ist die korrekte Asm-Syntax, mit sehr wenigen Ausnahmen, die im Handbuch. Deshalb ist Intel-Syntax richtig und AT&T-Syntax falsch: Die ISA stammt von Intel, die Dokumentation stammt von Intel und AMD, und diese Dokumentation verwendet Intel-Syntax.
Ich hatte also gehofft, dass die benutzerdefinierte Syntax zumindest zu einem sehr, sehr starken Prüfer führen würde, mindestens so gut wie der von Fil-C. Vielleicht mit einer Notluke, um so etwas zu sagen wie: "Ich weiß, es sieht so aus, als hätte ich xyz überschrieben, aber ich verspreche, ich habe es wirklich nicht getan."
Leider kompiliert das CPUID-Beispiel im Artikel offenbar, aber meiner Meinung nach sollte es das nicht: CPUID nimmt zwei Eingaben entgegen, in EAX und ECX, und das Beispiel hat vergessen, ECX als Eingabe zu binden. Man könnte argumentieren, dass CPUID sogar noch mehr Eingaben nimmt, wenn man in einer VM ist und etwas Besonderes tut, aber ECX ist wirklich ziemlich eindeutig.
- WalterBright
So macht es D für die x86_64:
https://github.com/dlang/dmd/blob/master/druntime/src/core/i...
Es ist die Statement-Form, verwendet Intel-Syntax, und der Compiler verfolgt, welche Register geändert werden.
- AshamedCaptain
> AT&T bäckt die Breite in den Mnemonic (movb, movw, movl, movq [...] Intels Syntax besteht darin, dem Speicheroperanden byte, word, dword oder qword voranzustellen, aber Odin verwendet direkt das Odin-Typsystem.
In GAS kann man das Breitensuffix vom Mnemonic weglassen, und in den meisten Intel-Assemblern kann man die Speichertyp-Operatoren wie byte weglassen. Sie raten es glücklich aus den Operanden. Das Problem ist, dass auf x86 (aber auch auf anderen ISAs, wenn auch in geringerem Maße) die verschiedenen Operandengrößen viele Nebeneffekte haben, weshalb jeder die Operandengröße explizit angibt, bis zu dem Punkt, dass der Autor/LLM offenbar glaubt, dass es obligatorisch ist, sie anzugeben.
Das untergräbt irgendwie die Schlagzeile des Artikels...
Morgen musst du eine 128-Bit-Ganzzahl in zwei Register übergeben, und deine ausgefallene Syntax wird dann auch zu einem unordentlichen Haufen von Hacks. Deshalb sieht die Inline-Assembly-Syntax von jedem so aus, weil sie die seltsamen Fälle abdecken wollen (die von gcc ist fast wie ein Geschichtsbuch). Normalerweise verwendet man Inline-Assembly, wenn man einen lächerlichen Grenzfall hat, wenn nicht, dann sollte man eher so etwas wie Intrinsics verwenden...
Außerdem vergisst es Watcom C, das eine vollständige, aber unübersichtliche Syntax für Inline-Assembly hat (die sich gut mit seiner Fähigkeit kombiniert, wirklich seltsame Aufrufkonventionen anzugeben).
- jcranmer
Eines der Probleme mit intelligenter Inline-Assembly-Syntax wie dieser ist, dass sie sich in vielen praktischen Fällen von Inline-Assembly als weniger hilfreich erweist.
Wenn man sich ansieht, wie zum Beispiel der Linux-Kernel Inline-Assembly verwendet, möchte er wirklich, dass die Inline-Assembly direkt an den Assembler weitergegeben wird. Es gibt viele Assembler-Direktiven in der Inline-ASM, um Dinge zu tun wie Anweisungen zu definieren, die der Assembler noch nicht kennt, oder ausgefallene Dinge wie den Aufbau eines Laufzeit-Instruction-Patching-Systems. Ich habe Inline-ASM in einem meiner Projekte, das zwischen 16-Bit-, 32-Bit- und 64-Bit-Anweisungen hin und her springt.
Ein weiteres Problem ist, dass größere Codeblöcke eine Vielzahl von Ansätzen verwenden, um Register zu speichern und wiederherzustellen, sodass man sich nicht zuverlässig auf die Anweisungssemantik verlassen kann, um herauszufinden, welche Register von einem vollständigen Assembly-Block überschrieben und welche erhalten bleiben. Diese Syntax funktioniert also wirklich nur für kleine Assembly-Stücke, und heutzutage ist es wahrscheinlich besser, für diese Zwecke tatsächlich echte Compiler-Intrinsics zu verwenden (was die meisten Produktionscompiler tun).
- genxy
Ein Forschungsgebiet, das es wert ist, ins Visier genommen zu werden, ist Typed Assembly Language