如何在C中执行这些操作?

时间:2010-05-03 20:05:11

标签: c assembly

我正在将一些汇编代码转换为C,以便能够在我必须使用的当前编译环境中使用它。

我已经达到了2个操作,我不知道如何翻译成C.任何人都知道怎么做?

在两者中,offset是无符号的32位整数,shift是有符号整数值。 C_FLAG是一个布尔。

OP1:

__asm {
    __asm mov ecx, shift
    __asm ror offset, cl
}

OP2:

__asm {
    __asm bt dword ptr C_FLAG, 0
    __asm rcr offset, 1
}

非常感谢您的专业知识。

P.S。:我不是原始开发人员,也没有看过很多x86汇编代码......

5 个答案:

答案 0 :(得分:2)

旋转正确的讨论:http://www.osix.net/modules/article/?id=320

图片说明:http://www.penguin.cz/~literakl/intel/r.html

希望这有帮助

答案 1 :(得分:0)

对于位移,根据您的第一个示例,使用<<运算符。在C语言中,没有用于移位的环绕,通常称为旋转。您必须自己实施该操作:

unsigned char carry;
carry = byte & 0x80; // Save the Most Significant bit for 8-bit byte.
byte <<= 1;  // Left shift by one, insert a 0 as the least significant bit.
byte |= carry;  // Put the rotated bit back into the byte.

某些处理器还具有旋转进位操作,该操作将在下一个班次中旋转进位值。这假定carry是一个全局变量。

要测试C语言中的位,您将使用&(二进制AND运算符)和~运算符(否定)。要测试8位字节中的最高有效位:

   if (byte & 0x80)
   {
      // bit is a 1
   }
   else
   {
      // bit is a 0
   }

尽管如此,你必须找出为什么使用 carry 标志(C_FLAG)并围绕它设计一个不同的系统。通常,进位位在其使用的汇编语言函数之外是无效的。某些紧密耦合的汇编语言函数可能违反此规则。在这种情况下,重写汇编语言而不是调试它。重新设计整个计划!

答案 2 :(得分:0)

第二个操作

__asm bt dword ptr C_FLAG, 0

将进位位标志设置为C_FLAG(so 1或0)

__asm rcr offset, 1

是使用进位标志作为第33位旋转进位左转,它是33位旋转。 (并且结果将第33位置于进位标志中。其中(我认为)与

相同
offset =  offset << 1 + C_FLAG ? 1:0

(除非您稍后关注进位标志)

编辑 - 出于某种原因,我正在阅读rcr作为rcl。更像是

offset = offset >> 1 | (C_FLAG ? 1<<31 : 0)

答案 3 :(得分:0)

虽然它或多或少被覆盖,但我会这样做:

OP 1:这是offsetshift个地方的右旋操作。在C中它可能是这样的:

offset = (offset >> shift) | (offset << (WORD_LENGTH - shift);

例如,您可以使用sizeof(void *) * 8来获取单词长度。


OP 2:我认为这个操作正在x86程序集中实现RRX操作。这是另一种旋转右旋操作,其中进位标志用于提供33位移位量。在C中它可能是这样的:

offset = (C_FLAG << 31) | (offset >> 1);

如果C_FLAG是进位标志,您应该找到更多关于您所拥有的代码中bool值实际用途的内容。

答案 4 :(得分:0)

假设标志不用于保持持久状态(这是一个合理的假设),OP1相当于:

/* Precondition: `*offset` is in range 0..0xFFFFFFFF */
void inline op1(unsigned long *offset, int shift)
{
    shift = ((unsigned)shift) % 32;

    if (shift)
        *offset = ((*offset >> shift) | (*offset << (32 - shift))) & 0xFFFFFFFFUL;
}

和OP2相当于:

/* Precondition: `*offset` is in range 0..0xFFFFFFFF */
void inline op2(unsigned long *offset, unsigned long C_FLAG)
{
    *offset = (*offset >> 1) | ((C_FLAG & 1) << 31);
}

(在32位long的系统上,自动满足前提条件。)