2010-06-19 10 views
7

Wie kann ich externe Definitionen wie LONG_MIN und LONG_MAX in ARM-Assembler-Code verwenden?Verwendung von C definiert in ARM-Assembler

Sagen wir my_arm.h wie folgt aussieht:

int my_arm(int foo); 

Lassen Sie uns sagen, dass ich ein my_main.c haben wie folgt:

... 
#include <limits.h> 
#include "my_arm.h" 
... 
int main (int argc, char *argv[]) 
{ 
    int foo=0; 
... 
    printf("My arm assembler function returns (%d)\n", my_arm(foo)); 
... 
} 

Und my_arm.s wie folgt aussieht:

.text 
    .align 2 
    .global my_arm 
    .type my_arm, %function 
my_arm: 
    ... 
    ADDS r1, r1, r2 
    BVS overflow 
    ... 
overflow: 
    LDR r0, LONG_MAX @ this is probably wrong, how to do it correctly? 
    BX lr @ return with max value 

Die vorletzte Zeile, ich bin nicht sicher, wie man richtig lädt, ich erinnere mich vage daran, irgendwo zu lesen, dass ich definieren musste LONG_MAX in .global, aber kann den Link zu einem funktionierenden Beispiel nicht mehr finden.

Ich Kompilieren mit Arm-linux-gnueabi-gcc Version 4.3.2

==================

UPDATE: Schätzen Sie die Vorschläge ! Leider habe ich immer noch Probleme mit der Syntax.

Zuerst machte ich eine kleine Header-Datei mylimits.h (jetzt in demselben Verzeichnis wie .S)

#define MY_LONG_MIN 0x80000000 

in my_arm.S i hinzugefügt folgendes:

... 
.include "mylimits.h" 
... 
ldr r7, =MY_LONG_MIN @ when it was working it was ldr r7, =0x80000000 
... 

Zwei Probleme mit diesem Ansatz.

Zuerst das größte Problem: das Symbol MY_LONG_MIN nicht erkannt wird ... so etwas noch nicht richtig

Zweitens: Syntax für .include mich nicht lassen umfassen <limits.h>, würde ich in mylimits hinzufügen. h, scheint ein bisschen kludgy, aber ich nehme an, das ist ok :)

Irgendwelche Zeiger?

Ich habe Zugang zu ARM-System-Entwicklerhandbuch Planung und Optimierung von Systemsoftware [2004] und ARM Architektur Referenzhandbuch [2000], mein Ziel ist XScale-IXP42x Familie 2 (V5L) rev though.

+4

Dont über ARM wissen, aber wenn Sie in Mips, durch zu .S auf die Verlängerung Umbenennung macht C Vorprozess die Datei. – Tom

+0

Verwenden Sie #include nicht .include und .S nicht .s, wie in der Antwort angegeben. Auf diese Weise können Sie eine gcc-Funktion ausnutzen, und alles sollte wie bei meinen Tests in x86 laufen. Assembly apart ist natürlich anders. – ShinTakezou

Antwort

11

Oft bedeutet die Dateierweiterung .s in Kleinbuchstaben, dass Assembler nicht durch den c Präprozessor übergeben werden sollte, während die Großbuchstaben-Erweiterung .S impliziert, dass es sollte. Es liegt nun an Ihrem Compiler, diese Konvention zu befolgen (gcc-Ports tun dies normalerweise), überprüfen Sie daher deren Dokumentation.

(BEARBEITEN: beachten Sie, dass dies bedeutet, Sie #include Direktiven verwenden können - aber denken Sie daran, dass die meisten der Dateien wäre nicht gültig Assembler (es sei denn, sie bestehen vollständig aus #define itions), so dass Sie möglicherweise schreiben müssen Ihre eigenen Header, der ist)


bearbeiten 5 Jahre später:

Beachten Sie, dass die armcc v5 Compiler dieses Verhalten unter linux folgt ... aber nicht auf Fenster.

+4

Wenn die GCC-Toolchain verwendet wird, wird das '__ASSEMBLER__'-Makro beim Vorverarbeitung von Assemblydateien definiert. Dies kann verwendet werden, um eine .h-Datei bei Bedarf in beiden Welten (asm und C) zu verwenden. Es ist jedoch möglicherweise immer noch am besten, die Elemente, die in beiden Welten funktionieren müssen, in separate Header zu trennen, falls dies möglich ist. Obwohl für etwas wie "LONG_MAX", das in einem Standard-Header definiert ist, haben Sie nicht viel Kontrolle über ... –

+0

Ja, es ist nicht viel mit Standard-Header verwenden! (Außer manchmal für Architektur-Header, die Dinge wie Memory-Mapped IO-Adressen definieren, die für den Zweck ausgelegt sind) – James

0

Ich habe gesehen füttern einfach GCC die Assembler Quelle vs Gas wird Ihnen erlauben, C wie Dinge in Assembler zu tun. Es ist wirklich ein bisschen beängstigend, wenn man auf Situationen stößt, in denen man gcc als Frontend zu Gas benutzen muss, um etwas zur Arbeit zu bringen, aber das ist eine andere Geschichte.

1

Was ich am Ende tun, ist dies:

in my_main.c

#include <limits.h> 
... 
int my_LONG_MAX=LONG_MAX; 

dann in my_arm.S

ldr r8, =my_LONG_MAX 
ldr r10, [r8] 

Es sieht convuluted und es ist (plus die Portabilität Gewinne sind in diesem Ansatz fraglich).

Es muss eine Möglichkeit geben, direkt in der Baugruppe auf LONG_MAX zuzugreifen. So würde ich gerne als vollständige Antwort akzeptieren.

+0

Wenn jemand eine bessere Lösung hinzufügen möchte, werde ich gerne diese Antwort akzeptieren – Sint

+0

Dies ist sehr hässlich. Warum versuchen Sie, type-size-related defines mit Assembler zu verwenden? Wenn Sie eine einzelne Architektur (asm) besitzen, dann schreiben Sie einfach die Konstante wörtlich. Es wird sich nicht ändern! –

+0

Oh, es ist schrecklich, gebe ich zu. :) Dies ist eine Implementierung einer Bibliotheksfunktion. Wenn es nach mir ginge, hätte ich es direkt als Konstante geschrieben. – Sint

2

Wenn Sie gcc und seinen Assembler verwenden, ist es einfach: Benennen Sie die Datei mit dem endgültigen .S, fügen Sie dann am Anfang #include <limits.h> hinzu und verwenden Sie, wo immer Sie die Konstante, z. ldr r0, SOMETHING; Ich habe Tests mit x86 gemacht, weil es das ist, was ich habe, aber das gleiche funktioniert, da es ein GCC-Feature ist.

0

Verwendung --cpreproc für armasm Option und

#include "my_arm.h" 

in my_arm.s hinzufügen.

es funktioniert für Keil ARM