我如何在 C 中执行这些 asm ROR 和 BT/RCR 操作?旋转或从另一个数字移入一位

发布于 2024-08-31 04:09:30 字数 423 浏览 5 评论 0原文

我正在将一些汇编代码转换为 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
}

非常感谢您的专业知识。

PS:我不是最初的开发者,也没有见过很多x86汇编代码...

I'm converting some assembly code to C to be able to use it with the current compiler environment I have to work with.

I've reached 2 operations I don't know how to translate to C. Anyone know how to do it?

In both, offset is an unsigned 32-bit integer and shift is a signed integer value. C_FLAG is a bool.

OP1:

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

OP2:

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

Thank you very much for your expertise.

P.S.: I'm not the original developer, nor I have seen many x86 assembly code...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

走过海棠暮 2024-09-07 04:09:30

向右旋转讨论: http ://www.osix.net/modules/article/?id=320 (web.archive)

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

希望这有帮助

rotate right discussion: http://www.osix.net/modules/article/?id=320 (web.archive)

pictorial descriptions: http://www.penguin.cz/~literakl/intel/r.html

Hope this helps

柏林苍穹下 2024-09-07 04:09:30

假设标志不用于保存持久状态(这是一个合理的假设),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 的系统上,先决条件自动满足)。

Assuming that the flags are not used to hold persistent state (which is a reasonable assumption), OP1 is equivalent to:

/* 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;
}

and OP2 is equivalent to:

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

(On systems with 32 bit long, the precondition is automatically satisfied).

超可爱的懒熊 2024-09-07 04:09:30

对于位移位,按照第一个示例,使用 << 运算符。在 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.

某些处理器还具有通过进位循环操作,该操作将在下一个移位中循环进位值。这假设进位是全局变量。

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

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

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

For bit shifting, as per your first example, use the << operator. In the C language there is no wrap-around for shifts, often termed as rotates. You would have to implement the operation yourself:

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.

Some processors also have a rotate through carry operation which will rotate the carry value in the next shift. This assumes that the carry be a global variable.

To test bits in the C language, you will use the & (binary AND operator) and maybe the ~ operator (negate). To test the most significant bit in an 8-bit byte:

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

With all that said, you will have to find out why the carry flag (C_FLAG) is used and design a different system around it. Generally, the carry bit is invalid outside of the assembly language function that it is used in. Some tightly coupled assembly language functions may violate this rule. In that case, rewrite the assembly language rather than debugging it. Redesign the whole program!

慈悲佛祖 2024-09-07 04:09:30

对于第二个操作,

__asm bt dword ptr C_FLAG, 0

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

__asm rcr offset, 1

是“循环进位左移”,这是使用进位标志作为第 33 位的 33 位循环。 相同

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

(结果将第 33 位放入进位标志中。这(我认为)与(除非您稍后关心进位标志)

编辑-出于某种原因,我将 rcr 读为 rcl。所以更像

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

for the second op

__asm bt dword ptr C_FLAG, 0

sets the carry bit flag to C_FLAG (so 1 or 0)

__asm rcr offset, 1

is Rotate Carry Left which is a 33 bit rotate using the carry flag as the 33rd bit. (and the results put the 33rd bit in the carry flag. Which (I think) is the same as

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

(unless you care about the carry flag later)

EDIT - for some reason I was reading rcr as rcl. So more like

offset = offset >> 1 | (C_FLAG ? 1<<31 : 0)
心碎的声音 2024-09-07 04:09:30

尽管它或多或少被覆盖,但我会这样做:

OP 1:这是对 offsetshift 位置的右旋转操作。在 C 中,可能是这样的:

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

例如,您可以使用 sizeof(void *) * 8 获取字长。


OP 2:我认为这个操作正在实现 RRX 操作在 x86 汇编中。这是另一种类型的右循环操作,其中进位标志用于提供要移位的 33 位数量。在 C 中,可能是这样的:

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

其中 C_FLAG 是进位标志,您应该找到更多有关 bool 值在您的代码中实际用途的信息。

Although it's more or less covered, I'd do it this way:

OP 1: It's a rotate right operation over offset, shift places. In C it could be something like this:

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

You could get the word length with sizeof(void *) * 8 for example.


OP 2: I think this op is implementing the RRX operation in x86 assembly. It's another type of rotate right operation where the carry flag is used to provide a 33 bit quantity to be shifted. In C it could be something like this:

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

Where C_FLAG is the carry flag, you should find more about what that bool value is really being used for in the code you have.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文