ROL / ROR上可变使用内联组件在Objective-C(ROL / ROR on variab

2019-09-02 01:11发布

我想在一个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指令。

Answer 1:

要在标准C做到这一点,你可以这样做:

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

大多数编译器将认识到,图案和它优化为单个指令(如果目标支持的话)反正。

你可以在这里阅读更多: http://en.wikipedia.org/wiki/Circular_shift#Implementing_circular_shifts



Answer 2:

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的时刻)。

当使用铛,你需要指定的操作数的大小。 所以,你会用rolbrolwrollrolq和朋友。 这是在锵的记录语言的兼容性| 内联汇编页。

这里的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 ++(即没有未定义的行为),它将不再被认为是一个旋转,而旋转指令将不会发生。

最后,还看不违反标准几乎恒定的时间旋转堆栈溢出。



文章来源: ROL / ROR on variable using inline assembly in Objective-C