« »

Assembler programmieren

a)

Level 1: Wissen

Assembly-Code beinhaltet Ausdrücke wie .globl _start, .data und .text. Was bedeuten diese Ausdrücke und warum sind sie wichtig?

Lösung
  • _start ist per Konvention der Einstiegspunkt für das Programm
  • .globl _start gibt an, dass dies ein globales Label ist, das auch für weitere verknüpfte Dateien sichtbar ist
  • .data und .text sind Bereiche im Speicher, die Daten und Anweisungen enthalten

b)

Level 3: Anwenden

Übersetzen Sie diesen C-Code in Assembler und erklären Sie, was er macht. Das Ergebnis soll in Register a0 gespeichert werden.

int main() {
    int a = 10;
    int b = 13;
    
    if (a < b) {
        return b - a;
    } else {
        return a - b;
    }
}

Hinweis: Nutzen Sie den QtRvSim zum Testen und vergessen Sie nicht, Ihre Lösung zu kommentieren und zu speichern.

Lösung
.globl _start
.text  

_start:
    li t0, 10        # Lade a in t0
    li t1, 13        # Lade b in t1
    blt t0, t1, then # if (a < b)
    sub a0, t0, t1   # a - b
    j end  

then:
    sub a0, t1, t0   # b - a
    
end:
    ebreak

c)

Level 3: Anwenden

Schreiben Sie ein Assembler-Programm für RISC-V, das die Multiplikation von 105 und 90 berechnet. Das Ergebnis soll in Register a0 gespeichert werden. Nutzen Sie Bit-Shiften für die Multiplikation und nutzen Sie das Template.

.globl _start
.text

_start:
    li a0, 0   # Ergebnis (a)
    li t0, 105 # Zahl 1 (x)
    li t1, 90  # Zahl 2 (y)

# Hier kommt Ihr Code.

end:
    ebreak
Lösung

Die naive Variante des Algorithmus addiert die erste Zahl einfach so oft zum Ergebnis, wie es die zweite Zahl vorgibt. Mit Hilfe des Bit-Shiftens lässt sich allerdings eine bessere Laufzeit erzielen. Der „Shift-and-Add“-Ansatz (vgl. Wikipedia-Beitrag zu Multiplikationsarten) ist weit verbreitet und kann wie folgt in Pseudocode ausgedrückt werden:

FUNKTION mul(x, y) {
    a = 0; // Akkumulator
    
    SOLANGE (y != 0) {
        // LSB = least significant bit
        WENN (LSB von y == 1) { 
            a = a + x;
        }
            
        x << 1;
        y >> 1;
    }
    RÜCKSPRUNG; // oder Programmende, je nach Kontext
}

.globl _start
.text

_start:
    li a0, 0           # Ergebnis (a)
    li t0, 105         # Zahl 1 (x)
    li t1, 90          # Zahl 2 (y)
loop:
    beq t1, zero, end  # springe zum Ende wenn y == 0
    andi t2, t1, 1     # LSB von y
    beq t2, zero, else # springe zu else wenn LSB(y) == 0
    add a0, a0, t0     # a = a + x
else:
    slli t0, t0, 1     # x << 1
    srli t1, t1, 1     # y >> 1
    j loop
end:
    ebreak

Lernziele

In dieser Aufgabe …

  • wiederholen die Studierenden Label und Direktiven in Assembler.
  • üben die Studierenden die Übersetzung von Hochsprachen zu Assembler.