2016-09-28 2 views
0

Ich habe einen minimalen Lua-Compiler für Bildungszwecke geschrieben, indem Sie den Lua-Code in Inline-Assembly in C mit gcc übersetzen.Wie man Fehler "mehr als 30 Operanden in 'asm'" mit Inline assembly mit gcc

Nach einer Weile, als meine generierte Ausgabe begann, mit mehr Operanden für deklarierte Variablen und Funktionen in C länger zu werden, begann dieser Fehler aufzutreten.

test.c: In function ‘int main()’: 
test.c:100:6: error: more than 30 operands in ‘asm’ 
    ); 

Wenn die einzige andere Infos googeln ich war some gcc mailing list from 2008 gefunden, aber sie sagte, dass es keine Korrekturen mit Ausnahme neu zu kompilieren gcc waren (was ich nicht interessiert bin).

Die ironische Sache ist, dass ich oft nicht einmal 30 Operanden habe und ich immer noch diesen Fehler bekomme!

Hier ist ein minimales Beispiel (mit 19 Operanden, mir nach wie vor, dass Fehler gibt)

// Standard functions 
void io_read(){} 
void io_write(){} 
void print(){} 
int main(){ 
    // Working vars decl 
    long _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7, _t8; 
    long factorial, i, n, x; 
    // Strings decl 
    const char* _s0 = "enter a number:"; 
    const char* _s1 = "*number"; 
    const char* _s2 = "factorial of "; 
    const char* _s3 = " is "; 
    asm("" // My inline asm code 
    : // Output symbols 
     [_s0] "+g" (_s0), 
     [_s1] "+g" (_s1), 
     [_s2] "+g" (_s2), 
     [_s3] "+g" (_s3), 
     [_t0] "+g" (_t0), 
     [_t1] "+g" (_t1), 
     [_t3] "+g" (_t3), 
     [_t4] "+g" (_t4), 
     [_t5] "+g" (_t5), 
     [_t6] "+g" (_t6), 
     [_t7] "+g" (_t7), 
     [_t8] "+g" (_t8), 
     [factorial] "+g" (factorial), 
     [i] "+g" (i), 
     [n] "+g" (n), 
     [x] "+g" (x) 
    : // Input symbols 
     [io_read] "r" (io_read), 
     [io_write] "r" (io_write), 
     [print] "r" (print) 
    : // Clobbers 
     "cc", "rax", "rbx", "rcx", "rdx" 
    ); 
} 

Meine gcc Version 6.2.1 20.160.830

Vielen Dank im Voraus!

+1

Verwenden Sie Variablen entweder erneut, oder erstellen Sie Tabellen (Arrays), und verwenden Sie Offsets in diesen Arrays, um Variablen zu erhalten (die vom Compiler in den Assemblycode eingefügt werden). –

+2

Ziehen Sie in Erwägung, eine ordnungsgemäße Montage anstelle einer Inline-Montage auszugeben. gcc hat ein Limit von 30 Operanden für die Inline-Assembly und es ist nicht geplant, dieses Limit zu entfernen. – fuz

+6

Wäre das Generieren von C-Code nicht viel einfacher und einfacher zu debuggen? Und warum generieren Sie nicht direkt eine Assembler-Datei? Nichts für ungut, aber diese C-Zwischenstufe sieht für mich wie Unsinn aus. – Olaf

Antwort

1

So fand ich keine direkte Lösung für das Problem, aber dank Ross Ridge konnte ich das Problem ziemlich gut umgehen.

Die erste Verbesserung, die ich tat, war "+ g" mit "g" wo möglich zu ändern. Offensichtlich zählt "+ g" als zwei Operanden, weil es sowohl Lesen als auch Schreiben erlaubt, so dass ich die möglichen Onces durch "g" ersetze, was nur Schreiben erlaubt.

Auch konnte ich meine Funktionen als Operanden vollständig entfernen, indem Sie sie in einen globalen Bereich verschieben und dann direkt mit "call print" anstelle von "call% [print]" aufrufen. Es sollte jedoch beachtet werden, dass dies nur mit Inline-C funktioniert und nicht mit Inline-C++ funktioniert.

Wenn Sie einen Compiler wie mich schreiben, würde ich empfehlen, von der Inline-Assembly wegzubleiben. Scheint mehr Ärger, einfach C-Funktionen manuell von Assembler aufrufen wäre einfacher, und ich würde sicherlich nicht einen Compiler in einem größeren Maßstab mit Inline-C machen.

EDIT: Ich begann auch "m" und "+ m" zu erzwingen anstatt "g" zu verwenden und Variablen auf den Stack zu zwingen, was gut zu funktionieren scheint.

+0

'" = g "' ist nur schreiben. '" g "' ist schreibgeschützt. IDK, warum Sie inline-asm überhaupt ausgeben möchten. Das scheint eine schreckliche Idee zu sein. Gib einfach reines C oder reines Asm (in ein '.s', das' main' definiert) aus. Funktionsaufrufe von Inline-Asm zu machen ist nicht einmal sicher, weil du gcc nicht sagen kannst, dass du die rote Zone überlisten willst. Die Verwendung von Funktionszeigern als Eingaben in Inline-Asm ist wirklich schrecklich, da Sie einen Register- oder Speicher-indirekten Aufruf durch einen tatsächlichen Funktionszeiger erhalten. –

+0

Sie lassen immer noch keine Erwähnung von '" = m "' oder '" = g "', was Sie verwenden sollten, wenn die Ausgabe schreibgeschützt ist. Ich würde empfehlen, so viele +/=/'g' Operanden zu verwenden, wie gcc es zulässt, und +/= /' m' für den Rest, da das Erzwingen von allem zum Stapel Müll-Asm macht. (Obwohl, wenn Sie bereits alle Register durcheinander bringen und die Zuweisung selbst vornehmen, was Sie wahrscheinlich tun müssen, da Sie nicht 'addl mem, mem' oder was auch immer erzeugen müssen, ist alles auf dem Stapel, außer den unmittelbaren Konstanten. Also sollten Sie immer noch "g" für Eingaben verwenden, um Unmittelbare zu ermöglichen.) –

Verwandte Themen