2013-05-05 2 views
5

Ich möchte ROR und ROL-Operationen auf Variablen in einem Objective-C-Programm ausführen. Ich kann es jedoch nicht schaffen - ich bin kein Montageexperte. HierROL/ROR auf Variable mit Inline-Assembly in Objective-C

ist, was ich bisher getan haben:

uint8_t v1 = ....; 
uint8_t v2 = ....; // v2 is either 1, 2, 3, 4 or 5 

asm("ROR v1, v2"); 

die Fehler, die ich bekommen ist:

Unbekannt Verwendung von Befehlsmnemonik mit unbekannter Größe Suffix

Wie kann ich repariere das?

Bearbeiten: Der Code muss keine Inline-Assembly verwenden. Ich habe jedoch keinen Weg gefunden, dies mit Objective-C/C++/C-Anweisungen zu tun.

+2

Sind Sie sicher, dass Sie eine Montage benötigen? Dies sollte nur benötigt werden, wenn dies ein Leistungsengpass ist. Für den normalen Gebrauch verwenden Sie 'var = (var << shift) | (var >> (sizeof (var) * 8-shift)) wäre in Ordnung. – Dave

+2

Für weitere Details, http://en.wikipedia.org/wiki/Circular_shift#Implementing_circular_shifts – Dave

+0

nett. Danke für Ihre Antwort. Da dies die Frage beantwortet, wenn Sie es zu einer Antwort machen, werde ich es akzeptieren. –

Antwort

2

dies in Standard-C zu tun, können Sie tun:

var = (var << shift) | (var >> (sizeof(var)*CHAR_BIT-shift)) 

Die meisten Compiler werden diese Muster erkennen und es auf einen einzigen Befehl optimieren (wenn das Ziel unterstützt) sowieso.

können Sie mehr hier lesen: http://en.wikipedia.org/wiki/Circular_shift#Implementing_circular_shifts

+1

'++ posting ++'; Beachten Sie besonders die _references_ im Wikipedia-Artikel, in denen die von 'gcc' /' clang' angewandte Optimierung in Bezug auf das Konvertieren dieser Art von Code in Hardware-Rotate, wo verfügbar, zitiert wird. Da Objective C/C++ immer 'gcc' /' clang' bedeutet, kann davon ausgegangen werden, dass die Optimierung angewendet wird. Für ARM ist _not_ coding der Rotate als _separate Instruction_ besser, weil der Barrel Shifter die Rotation in jede Arithmetik "integrieren" kann; 'var = rotate (var, xxx) + 1 'ist eine _single-Anweisung_ in ARM, aber nur erfassbar, wenn _nicht_ als Funktionsaufruf/Inline-Asm aufgeteilt ist. –

+0

Vielen Dank für Ihre Antwort. Es ist sehr hilfreich. Weißt du, wie man es mit Inline-Assemblierung macht? Ich frage, weil ich neugierig bin, wie der Code aussieht und wie man lokale Variablen in diesem Assemblercode referenziert. –

+0

Wie es in der Assembly codiert wird, hängt von Ihrer Zielarchitektur ab. Ich kann selbst keine Assembly schreiben (was ich lernen möchte), aber aufgrund des Aussehens der Fehlermeldung würde ich sagen, dass Sie es sagen müssen, wenn Sie eine 32-Bit- oder 64-Bit-Operation oder so etwas wollen. Vielleicht hilft diese Seite: http://sourceware.org/binutils/docs/as/i386_002dMnemonics.html – Dave

1
var = (var << shift) | (var >> (sizeof(var)*CHAR_BIT-shift)) 

diesen Code nicht anwenden. Es hat ein undefiniertes Verhalten, wenn shift 0 ist. Intels ICC entfernt die Anweisungen mit dem undefinierten Verhalten. Ich kenne das aus erster Hand.

Außerdem wird der Code nicht Clanning oder GCC Undefined Behavior Desinfektionsmittel übergeben. Zum Lesen siehe Clang's Controlling Code Generation oder GCC Undefined Behavior Sanitizer – ubsan.


die Fehler, die ich bekommen ist:
Unbekannte Verwendung Befehlsmnemonik mit unbekannter Größe Suffix

Sie sind eine von zwei Werkzeugen - entweder GCC oder Clang. Ich denke, dass Apple standardmäßig um Xcode 4 nach Clang wechselt, also verwenden Sie wahrscheinlich Clang.

GCC wird an GNU AS (GAS) delegieren, während Clang seinen Integrated Assembler verwenden wird. In beiden Fällen sollten Sie die Inline-Assembly AT & T verwenden, da die Clang-Unterstützung für die Intel-Assembly nicht korrekt ist. Zum Beispiel Clang can't generate a negate instructions (a.k.a. LLVM Bug 24232) im Moment.

Wenn Sie Clang verwenden, müssen Sie die Operandengröße angeben. So werden Sie rolb, rolw, roll und rolq und Freunde verwenden. Dies ist auf Clangs Language Compatibility | Inline Assembly Seite dokumentiert.

Hier ist, was die 8-Bit drehen wie folgt aussieht:

// Immediate 
inline word8 rotlImmediate8 (word8 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rolb %1, %0" : "+mq" (x) : "I" ((unsigned char)y)); 
    return x; 
} 

// Immediate or register 
inline word8 rotl8 (word8 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rolb %1, %0" : "+mq" (x) : "cI" ((unsigned char)y)); 
    return x; 
} 

// Immediate 
inline word8 rotrImmediate8 (word8 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rorb %1, %0" : "+mq" (x) : "I" ((unsigned char)y)); 
    return x; 
} 

// Immediate or register 
inline word8 rotr8 (word8 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rorb %1, %0" : "+mq" (x) : "cI" ((unsigned char)y)); 
    return x; 
} 

Die 8-Bit-Wort Sonderbehandlung auf Einschränkungen muss. Sie können +g nicht verwenden; Sie brauchen eher +mq.

Hier ist die 16-Bit-Wort-Version:

// Immediate 
inline word16 rotlImmediate16 (word16 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rolw %1, %0" : "+g" (x) : "I" ((unsigned char)y)); 
    return x; 
} 

// Immediate or register 
inline word16 rotl16 (word16 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rolw %1, %0" : "+g" (x) : "cI" ((unsigned char)y)); 
    return x; 
} 

// Immediate 
inline word16 rotrImmediate16 (word16 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rorw %1, %0" : "+g" (x) : "I" ((unsigned char)y)); 
    return x; 
} 

// Immediate or register 
inline word16 rotr16 (word16 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rorw %1, %0" : "+g" (x) : "cI" ((unsigned char)y)); 
    return x; 
} 

Und hier ist die 32-Bit-Version:

// Immediate 
inline word32 rotlImmediate32 (word32 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("roll %1, %0" : "+g" (x) : "I" ((unsigned char)y)); 
    return x; 
} 

// Immediate or register 
inline word32 rotl32 (word32 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("roll %1, %0" : "+g" (x) : "cI" ((unsigned char)y)); 
    return x; 
} 

// Immediate 
inline word32 rotrImmediate32 (word32 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rorl %1, %0" : "+g" (x) : "I" ((unsigned char)y)); 
    return x; 
} 

// Immediate or register 
inline word32 rotr32 (word32 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rorl %1, %0" : "+g" (x) : "cI" ((unsigned char)y)); 
    return x; 
} 

Schließlich ist hier die 64-Bit-Version. Sie sollten es mit etwas wie __amd64 oder __x86_64__ schützen. Da der Rotationsbetrag [0,63] sein kann, verwenden Sie die J-Einschränkung.

// Immediate 
inline word64 rotlImmediate64 (word64 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rolq %1, %0" : "+g" (x) : "J" ((unsigned char)y)); 
    return x; 
} 

// Immediate or register 
inline word64 rotl64 (word64 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rolq %1, %0" : "+g" (x) : "cJ" ((unsigned char)y)); 
    return x; 
} 

// Immediate 
inline word64 rotrImmediate64 (word64 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rorq %1, %0" : "+g" (x) : "J" ((unsigned char)y)); 
    return x; 
} 

// Immediate or register 
inline word64 rotr64 (word64 x /*value*/, unsigned int y /*rotate*/) 
{ 
    __asm__ ("rorq %1, %0" : "+g" (x) : "cJ" ((unsigned char)y)); 
    return x; 
} 

Clang keine Konstanten wie GCC ausbreiten, so dass Sie Probleme mit dem Direkt-8-Version der dreht sich haben könnte. Siehe auch Force Clang to “perform math early” on constant values auf Stack Overflow und LLVM Bug 24226.


Sie sollten sich die Zeit nehmen und John Regehr des Safe, Efficient, and Portable Rotate in C/C++ besuchen. Seine Art von Anti-Höhepunkt. Es sagt, sobald Sie die richtige Rotation in C/C++ schreiben (d. H. Kein undefiniertes Verhalten), wird es nicht länger als Rotation erkannt, und die Rotationsanweisung wird nicht generiert.

Schließlich, siehe auch Near constant time rotate that does not violate the standards auf Stack Overflow.