Aliase: Unterschied zwischen den Versionen

Aus C und Assembler mit Raspberry
KKeine Bearbeitungszusammenfassung
KKeine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
== Was sind Aliase? ==
== Was sind Aliase? ==


Ein **Alias** ist eine alternative Schreibweise für eine Instruktion – sozusagen ein **„freundlicher“ Name** für komplexere Maschinenbefehle. Aliase machen den Code **lesbarer und intuitiver**, verändern aber **nicht** den Maschinencode, der letztlich generiert wird.
Ein "Alias" ist eine alternative Schreibweise für eine Instruktion – sozusagen ein „freundlicher“ Name für komplexere Maschinenbefehle. Aliase machen den Code "lesbarer und intuitiver", verändern aber "nicht" den Maschinencode, der letztlich generiert wird.


Beispiel:
Beispiel:


```asm
<syntaxhighlight lang="asm">
mov x0, x1
mov x0, x1
```
</syntaxhighlight>


Dieser Befehl existiert **nicht als eigener Maschinenbefehl**, sondern ist ein **Alias** für:
Dieser Befehl existiert "nicht als eigener Maschinenbefehl", sondern ist ein "Alias" für:


```asm
<syntaxhighlight lang="asm">
orr x0, x1, xzr
orr x0, x1, xzr
```
</syntaxhighlight>


Der Befehl `orr` (bitweises ODER) mit dem Wert `xzr` (Zero-Register) ergibt effektiv `mov`.
Der Befehl `orr` (bitweises ODER) mit dem Wert `xzr` (Zero-Register) ergibt effektiv `mov`.
Zeile 31: Zeile 31:
Beim Disassemblieren mit `objdump` oder `gdb` siehst du **immer den echten Maschinenbefehl**, nicht den Alias.
Beim Disassemblieren mit `objdump` oder `gdb` siehst du **immer den echten Maschinenbefehl**, nicht den Alias.


```asm
<syntaxhighlight lang="asm">
mov x0, x1    ; geschrieben im Assembler
mov x0, x1    ; geschrieben im Assembler
```
</syntaxhighlight>


Ergibt in `objdump -d`:
Ergibt in `objdump -d`:
```
<syntaxhighlight lang="asm">
orr x0, x1, xzr
orr x0, x1, xzr
```
</syntaxhighlight>


⚠️ Das kann verwirrend sein, wenn du Quellcode und disassemblierten Code vergleichst!
⚠️ Das kann verwirrend sein, wenn du Quellcode und disassemblierten Code vergleichst!
Zeile 49: Zeile 49:


- Quelltext (Alias):
- Quelltext (Alias):
  ```asm
<syntaxhighlight lang="asm">
   mov x0, x1
   mov x0, x1
  ```
</syntaxhighlight>
- Assembler-Expansion:
- Assembler-Expansion:
  ```asm
<syntaxhighlight lang="asm">
   orr x0, x1, xzr
   orr x0, x1, xzr
  ```
</syntaxhighlight>
- Maschinencode (Hex):
- Maschinencode (Hex):
  ```text
<syntaxhighlight lang="asm">
   0xaa0103e0
   0xaa0103e0
  ```
</syntaxhighlight>


➡️ Ob du `mov x0, x1` oder `orr x0, x1, xzr` schreibst, ergibt **denselben Maschinencode**.
➡️ Ob du `mov x0, x1` oder `orr x0, x1, xzr` schreibst, ergibt **denselben Maschinencode**.
Zeile 94: Zeile 94:
== Beispiel: `alias_test.s` ==
== Beispiel: `alias_test.s` ==


```asm
<syntaxhighlight lang="asm">
     .section .text
     .section .text
     .global _start
     .global _start
Zeile 116: Zeile 116:
     // Alias: ret -> br x30
     // Alias: ret -> br x30
     ret
     ret
```
</syntaxhighlight>


---
---
Zeile 122: Zeile 122:
=== Bauen und disassemblieren ===
=== Bauen und disassemblieren ===


```bash
<syntaxhighlight lang="shell">
as alias_test.s -o alias_test.o
as alias_test.s -o alias_test.o
ld alias_test.o -o alias_test
ld alias_test.o -o alias_test
objdump -d alias_test
objdump -d alias_test
```
</syntaxhighlight>


---
---
Zeile 132: Zeile 132:
=== Beispielausgabe von `objdump -d alias_test` ===
=== Beispielausgabe von `objdump -d alias_test` ===


```asm
<syntaxhighlight lang="asm">
0000000000401000 <_start>:
0000000000401000 <_start>:
   401000:  aa0103e0    orr    x0, x1, xzr
   401000:  aa0103e0    orr    x0, x1, xzr
Zeile 140: Zeile 140:
   401010:  d503201f    nop
   401010:  d503201f    nop
   401014:  d65f03c0    ret
   401014:  d65f03c0    ret
```
</syntaxhighlight>


Du siehst:
Du siehst:
Zeile 159: Zeile 159:
Wenn du **keine Aliase im Disassembly** möchtest (d. h. nur „echte“ Instruktionen), kannst du `objdump` so verwenden:
Wenn du **keine Aliase im Disassembly** möchtest (d. h. nur „echte“ Instruktionen), kannst du `objdump` so verwenden:


```bash
<syntaxhighlight lang="shell">
objdump -d -M no-aliases alias_test
objdump -d -M no-aliases alias_test
```
</syntaxhighlight>


Das zeigt dir, wie es **der CPU intern** wirklich vorliegt.
Das zeigt dir, wie es **der CPU intern** wirklich vorliegt.

Version vom 10. April 2025, 17:22 Uhr

Was sind Aliase?

Ein "Alias" ist eine alternative Schreibweise für eine Instruktion – sozusagen ein „freundlicher“ Name für komplexere Maschinenbefehle. Aliase machen den Code "lesbarer und intuitiver", verändern aber "nicht" den Maschinencode, der letztlich generiert wird.

Beispiel:

mov x0, x1

Dieser Befehl existiert "nicht als eigener Maschinenbefehl", sondern ist ein "Alias" für:

orr x0, x1, xzr

Der Befehl `orr` (bitweises ODER) mit dem Wert `xzr` (Zero-Register) ergibt effektiv `mov`.

---

Warum macht man das?

- **Lesbarkeit**: `mov x0, x1` ist leichter verständlich als `orr x0, x1, xzr`. - **Portabilität**: Viele Architekturen haben einen `mov`, und Entwickler erwarten diesen. - **Compilerfreundlich**: Auch Compiler wie `clang` oder `gcc` generieren „Alias-ähnlichen“ Code.

---

Was macht `objdump` daraus?

Beim Disassemblieren mit `objdump` oder `gdb` siehst du **immer den echten Maschinenbefehl**, nicht den Alias.

mov x0, x1     ; geschrieben im Assembler

Ergibt in `objdump -d`:

orr x0, x1, xzr

⚠️ Das kann verwirrend sein, wenn du Quellcode und disassemblierten Code vergleichst!

---

Was wird wirklich generiert?

Nehmen wir `mov x0, x1`:

- Quelltext (Alias):

  mov x0, x1

- Assembler-Expansion:

  orr x0, x1, xzr

- Maschinencode (Hex):

  0xaa0103e0

➡️ Ob du `mov x0, x1` oder `orr x0, x1, xzr` schreibst, ergibt **denselben Maschinencode**.

---

Bekannte Aliase im ARM64-Assembler

| Alias | Entsprechender Instruktionscode | Beschreibung | |----------------|------------------------------------------------|------------------------------------------| | `mov x0, x1` | `orr x0, x1, xzr` | Kopiere Register | | `mov x0, #0` | `movz x0, #0` | Setze Register auf 0 | | `cmp x0, x1` | `subs xzr, x0, x1` | Vergleich über Subtraktion ohne Ergebnis | | `neg x0, x1` | `sub x0, xzr, x1` | Negation | | `nop` | `hint #0` | Kein-Operation (für Alignment etc.) | | `ret` | `br x30` | Rücksprung aus Funktion | | `b label` | `b label` (kein Alias) | Unbedingter Sprung | | `bl label` | `bl label` (kein Alias) | Sprung mit Link (Funktionsaufruf) | | `movk/movz/movn`| Literalladen in 16-Bit-Chunks | Register initialisieren mit Immediate |

---

Warum ist das wichtig?

1. **Disassembler zeigen keine Aliase** → verwirrend bei Analyse. 2. **Debugging wird leichter**, wenn man den echten Maschinenbefehl kennt. 3. **Assemblerfehler** können entstehen, wenn man glaubt, `mov` sei ein „echter“ Befehl mit eigenen Regeln.

--- Hier ist ein einfaches Beispielprogramm in ARM64-Assembler mit typischen **Alias-Instruktionen**, das du kompilieren und mit `objdump` untersuchen kannst. Danach zeige ich dir, wie die `objdump`-Ausgabe dazu aussieht.

---

Beispiel: `alias_test.s`

    .section .text
    .global _start

_start:
    // Alias: mov x0, x1 -> orr x0, x1, xzr
    mov x0, x1

    // Alias: mov x2, #0 -> movz x2, #0
    mov x2, #0

    // Alias: cmp x0, x1 -> subs xzr, x0, x1
    cmp x0, x1

    // Alias: neg x3, x4 -> sub x3, xzr, x4
    neg x3, x4

    // Alias: nop -> hint #0
    nop

    // Alias: ret -> br x30
    ret

---

Bauen und disassemblieren

as alias_test.s -o alias_test.o
ld alias_test.o -o alias_test
objdump -d alias_test

---

Beispielausgabe von `objdump -d alias_test`

0000000000401000 <_start>:
  401000:   aa0103e0    orr     x0, x1, xzr
  401004:   d2800002    movz    x2, #0x0
  401008:   eb01001f    subs    xzr, x0, x1
  40100c:   cb040060    sub     x3, xzr, x4
  401010:   d503201f    nop
  401014:   d65f03c0    ret

Du siehst:

| Quellcode Alias | Disassembler zeigt | Bedeutung | |----------------------|------------------------|---------------------------------------------| | `mov x0, x1` | `orr x0, x1, xzr` | Kopiere x1 nach x0 | | `mov x2, #0` | `movz x2, #0x0` | Setze x2 auf 0 | | `cmp x0, x1` | `subs xzr, x0, x1` | Vergleiche x0 mit x1 | | `neg x3, x4` | `sub x3, xzr, x4` | x3 = -x4 | | `nop` | `hint #0` | Kein Effekt | | `ret` | `ret` | Rücksprung über x30 |

---

Weitere Analyse

Wenn du **keine Aliase im Disassembly** möchtest (d. h. nur „echte“ Instruktionen), kannst du `objdump` so verwenden:

objdump -d -M no-aliases alias_test

Das zeigt dir, wie es **der CPU intern** wirklich vorliegt.