skip to main content

kiesler.at

Alpha C Inline-Assembler
updated by rck, 2004-10-08

C war schon seit Anfang an eine sehr maschinennahe Programmiersprache. Dadurch entstanden einerseits Probleme wie Bufferoverflows ('effizientes' Speichermanagement). Andererseits wichtige Konzepte wie Inline-Assembler. Inline-Assembler ist oft nicht nur einfacher zu durchschauen, weil der C-Compiler das ,,Housekeeping'' (Adressen-Ausrichtung, etc.) macht. Sondern auch fast so effizient wie ,,pure Assembler''.
1 | 2 | 3 | 4 | 5 | 6

Inline Assembler in C?

In C gab es schon lange vor Turbo Pascal Inline-Assembler. Es gibt mindestens zwei Arten von C-Inline-Assembler (wenn nicht mehr); ich möchte hier die für die Übersetzerbau-Übung auf der TU-Wien relevante Variation vorstellen.

Ein Beispiel
01: unsigned long count0s(unsigned long a) {
02:    unsigned long i, r=0;
03:
04:    asm volatile(
05:      "not %1, %0 \n\t"
06:      "ctpop %0, %0 \n\t":
07:      "=r"(r): "r"(a)
08:    );
09:    return(r);
10: }

Das ist das asma Beispiel aus der Übersetzerbau-Übung im Sommersemester 2004, mit Inline-Assembler gelöst.

Interessant sind die Zeilen 04-08, ich werde gleich auf sie eingehen.

Der Inline-Assemblerblock

Ein Inline-Assemblerblock für GCC auf der Alpha beginnt mit "asm volatile". Asm ist klar, steht für Assembler. Aber volatile? Volatile heißt soviel wie: Bitte, lieber Compiler, lass den Code so wie er ist und tu ihn nicht weiter optimieren.

Volatile kann übrigens auch bei Variablen verwendet werden. Die werden dann auf jedenfall von C verwendet, auch wenn sie wegoptimiert werden könnten. Kann beim Debugging nützlich sein.

Schreib- und Leseregister

Ich gehe nicht der Reihe nach vor, sondern springe gleich zu Zeile 07. "=r"(r) heißt soviel wie: Ich möchte mir einen Register reservieren, dessen Wert im Anschluß an den asm volatile Block in Variable r landet.

"=" steht für Schreibzugriff, das erste "r" für Register und das "(r)" für Variable r. Die wurde in Zeile 02 mir unsigned long r=0 definiert.

Gleich neben unserem Schreibregister finden wir noch ein Leseregister, es ist in unserem Fall der Übergabeparameter a. Man beachte das Fehlende =.

Die Schreib- und Leseregister werden vom Compiler durchnummeriert. Der allererste Register ist in unserem Fall der, in dem wir die Variable r speichern. Er bekommt die Bezeichnung %0. Der zweite Register wird mit dem Wert vom Übergabeparameter a initialisiert, er erhält Bezeichnung %1.

Inline-Assembler Sections

Wir haben in einem Inline-Assembler Block drei Sections (ich nenne die einfach mal so, ist keine offizielle Bezeichnung) die durch ":" getrennt werden. Die beiden letzten, die Schreib- und Leseregisterdeklaration hatten wir bereits. Jetzt zum Hauptdarsteller, den Assemblerstatements.

Im wesentlichen ist hier unser Assembler-Programm, in einer sehr puristischen Form. In Zeile 05 negiert not den Übergabeparameter a und sichert ihn in r. In Zeile 06 zählt der Alphaprozessor mit ctpop die Anzahl der Einsen -- die Ursprünglich ja alle Nuller waren -- und schreibt das Ergebnis wieder nach r (zumindest im logischen Ablauf, praktisch passiert das alles mit Registern!).

Interessantes Detail hier vielleicht die \n\t Kombinationen gegen Zeilenende. Wozu? Aus Kosmetik-gründen und der Übersicht wegen. Sieht man nämlich im Anschluss an den Sourcecode (erhalten wir mit gcc -mcpu=ev6 -S -O inline.c), sind dort die Zeilen in Reih' und Glied ausgerichtet.

Der erzeugte Assemblercode

        .file 1 "inline.c"
        .set noat
        .set noreorder
        .arch ev6
.text
        .align 5
        .globl count0s
        .ent count0s
count0s:
        .frame $30,0,$26,0
$count0s..ng:
        .prologue 0
        not $16, $0
        ctpop $0, $0

        ret $31,($26),1
        .end count0s
        .ident "GCC: (GNU) 2.95.2 19991024 (release)"

1 | 2 | 3 | 4 | 5 | 6



RSSComments - Make a comment
The comments are owned by the poster. We are not responsible for its content.
  • Eleganter

    Posted on 2004-05-22 01:25:06 By rck[110]

    static inline long
    __attribute__ ((unused))
    count_population (volatile long val)
    {
    long ret;

    __asm__ __volatile__ (
    "ctpop %1,%0\n\t"
    : "=&r"(ret)
    : "r"(val));

    return ret;
    }

    So meinte ich das im Informatikforum. Wofür das attribute(unused) ist, weiß ich auch nicht genau, aber bei der glibc wird's immer so geschrieben, wird schon nicht so falsch sein.

    Und bei deinem ersten Beispiel würd ich das "not" weglassen und stattdessen bei den Eingangs-Constraints einfach ~a statt a schreiben - das gibt dem Compiler mehr Freiheit zu optimieren, wenn ihm danach ist.

    [Reply ]

RSSAll Articles
2008, 2007, 2006, 2005, 2004

What's Related

Documents

Übersetzerbau

Link Manager

Übersetzerbau
Programming

Article Manager

Übersetzerbau
Programming

FAQ

Übersetzerbau

Photo Albums

Programming

RSS News Feeds

Programming

Announcements

Programming

Web Pages

Programming

Latest Updates

AdministrativeTexts
updated by freddiemac1993, 2013-06-14
wiki

Re: adventures
created by brittdavis10, 2012-02-23 (1 rply, 3 views)
thread

Re: how to run phpwebsite...
created by alexander, 2011-08-25 (2 rpls, 3607 views)
thread

Re: Forum tags
created by HaroldFaragher, 2011-08-22 (3 rpls, 8488 views)
thread


Zu den KO2100 Foren