我想在一个Objective-C程序的变量进行ROR和ROL操作。 但是,我不能管理它 - 我不是专家装配。
以下是我迄今所做的:
uint8_t v1 = ....;
uint8_t v2 = ....; // v2 is either 1, 2, 3, 4 or 5
asm("ROR v1, v2");
我得到的错误是:
未知的使用指令助记符与未知大小后缀
我怎样才能解决这个问题?
编辑:该代码并不需要使用内联汇编。 但是,我还没有找到一个办法做到这一点使用Objective-C / C ++ / C指令。
要在标准C做到这一点,你可以这样做:
var = (var << shift) | (var >> (sizeof(var)*CHAR_BIT-shift))
大多数编译器将认识到,图案和它优化为单个指令(如果目标支持的话)反正。
你可以在这里阅读更多: http://en.wikipedia.org/wiki/Circular_shift#Implementing_circular_shifts
var = (var << shift) | (var >> (sizeof(var)*CHAR_BIT-shift))
不要使用此代码。 它不确定的行为时shift
为0英特尔的ICC删除与未定义行为的语句。 我知道的第一手资料。
此外,该代码将无法通过锵的或GCC的不确定行为液。 对于阅读,请锵的控制代码生成或GCC的未定义行为消毒剂- ubsan 。
我得到的错误是:
未知的使用指令助记符与未知大小后缀
您正在使用的两个工具一个 - 无论是GCC或锵。 我认为苹果切到锵周围的Xcode 4的默认,所以你可能正在使用锵。
GCC将委托给GNU AS(GAS),而锵将利用其集成的汇编。 在这两种情况下,你应该使用AT&T的内联汇编,因为Intel汇编锵支持是参差不齐。 例如, 锵不能生成否定指令 (又名LLVM错误24232的时刻)。
当使用铛,你需要指定的操作数的大小。 所以,你会用rolb
, rolw
, roll
和rolq
和朋友。 这是在锵的记录语言的兼容性| 内联汇编页。
这里的8位旋转的样子:
// 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;
}
8位字需要在限制特殊处理。 不能使用+g
; 而你需要+mq
。
这里的16位字的版本:
// 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;
}
而这里的32位版本:
// 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;
}
最后,这里的64位版本。 你应该像保护它__amd64
或__x86_64__
。 由于旋转量能[0,63]
您使用J
约束。
// 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;
}
锵不传播常数像GCC,所以你可能有立即-8版本旋转的麻烦。 另请参阅部队锵对常量“提前执行数学”在堆栈溢出或LLVM的Bug 24226 。
你应该花时间参观约翰·雷吉汉弗的++安全,高效,便携旋转在C / C 。 它那种反高潮的。 它说,一旦你用C写正确的旋转/ C ++(即没有未定义的行为),它将不再被认为是一个旋转,而旋转指令将不会发生。
最后,还看不违反标准几乎恒定的时间旋转堆栈溢出。