ARM Assembler in MSVC++
« | 18 Jun 2022 | »Mit meinem neuen ARM-PC und dem ebenso neuen Visual Studio 2022 Preview für ARM64 eröffnet sich mir wieder ein neues Kapitel in der Softwareentwicklung:
ARM32 und ARM64 Assembly Language.
Denn nun kann ich beides live debuggen.
Einrichtung in Visual Studio
Wenn man *.asm
Dateien einem Visual Studio Projekt hinzufügt und
die Build Dependencies
- Build Customizations
- masm Targets
aktiviert hat, ist lediglich X86 und X64 Support (ml.exe
) verfügbar.
Für die ARM Entwicklung braucht man aber den ARM Assembler (armasm.exe
)
und dieser kann über den marmasm
Eintrag der
Visual C++ Build Customization Files
aktiviert werden.
Hat man in seinem MSVC Projekt parallel auch masm
aktiviert, dann sollte
man für jede Zielplattform die korrekten *.asm
Dateien einschließen und
ihren Item Type
in den Properties
korrekt setzen.
Dieser lautet dann nämlich Microsoft ARM Assembler
(und nicht wie sonst
Microsoft Macro Assembler
)
In älteren Varianten von Visual Studio fehlt ein solches Custom-Target.
Hier kann man sich entweder das masm
Target-File hernehmen und anpassen
oder von Anfang an neu erstellen.
Oder man definiert einen generischen Kommandoaufruf.
Am Ende muss mindestens ein:
armasm64.exe "path\to\my_code.asm" -o "ARM64\Debug\my_code.obj"
dabei herauskommen.
Noch kein direkter CMake Support
CMake unterstützt den MARMASM
leider noch nicht.
Es gibt einige Diskussions-Hinweise im Netz darauf, dass im Modul
CMakeDetermineASM_MASMCompiler.cmake
ein Patch notwendig wäre, weil dort
nur ML64
und ML
erkannt werden.
Ich vermute aber, dass Microsoft das in der nächsten Preview, aller-spätestens aber mit dem nächsten Visual Studio Produkt nachliefern wird.
Vorläufig muss ich alle Assembler-Tests manuell einrichten.
Update 2023:
Ab CMake 3.26 (3.25.2023 nightly builds) ist der Sprachdialekt “ASM_MARMASM” enthalten und erzeugt damit alle notwendigen MSVC Einstellungen automatisch.
ARM Syntax: Ja nicht auf das Leerzeichen vergessen!
Meine ersten Versuche mit kopierten Zeilen aus dem Netz scheiterten alle mit seltsamen Fehlern wie:
error A2034: unknown opcode: .text
wenn die erste Zeile AREA |.text|,CODE,READONLY
übersetzt wird.
Eine ARM Assembly Language Zeile ist immer nach dem gleichen Schema
aufgebaut, nämlich:
{symbol} {instruction|directive|pseudo-instruction} {;comment}
Und damit muss jede Zeile entweder mit einer Zeilenmarke anfangen
(Funktionsnamen oder Sprung-Label),
oder eben mit einem Leerzeichen oder TAB
.
Direktiven wie AREA
, EXPORT
oder ENDP
und alle CPU Anweisungen müssen
also immer eingerückt werden:
1 ;demo.asm: Correct! With space before directives/instructions 2 AREA |.text|,CODE,READONLY ; location + type of generated code 3 4 EXPORT my_add_func ;declare "my_add_func" as public function 5my_add_func PROC ;"my_add_func" entry-point symbol 6 add x0, x0, x1 ; ret = param_1 + param2 7 ret ;ARM return instruction 8 ENDP ;end of procedure "my_add_func" 9 10 END ;end of assembly file
Kaum hat man es richtig gemacht, lässt sich die Assemblerzeile mit dem ARM64 Assembler übersetzen und aus C++ mit dem Prototyp
aufrufen.
Fazit
Nun kann ich also meine Stack-Switching-Routinen auch auf ARM Plattformen portieren und das wiederrum eröffnet ein weiteres spannendes Feld:
EFI-Apps auf ARM Hardware
Doch bis ich mich ausreichend gut mit ARM Assembler Codes auskenne, wird wohl
noch der eine oder andere Test notwendig sein.
Schließlich habe ich bisher immer nur mit X86 gearbeitet und kenne die
weit gestreuten Möglichkeiten der ARM Architektur noch nicht.
Zumindest freue ich mich, dass ich jetzt wenigstens alle Windows-Plattformen
mit Assemblercode beglücken kann.
Doch auch das wird nicht das Ende sein … denn mein
Raspberry PI verdient eine
mindestens genau so gute Linux Abdeckung.