不带进位的变量左按位循环?

发布于 2024-10-31 11:49:46 字数 499 浏览 2 评论 0原文

让我们有一个任务,在 C++ 中对变量 a 进行左位旋转(不带进位)。我认为,使用内联汇编来执行此例程会更好,不是吗?

例如,如果我们有a == 100 == 0b<一堆零>1100100a LR 1应该提供0b1001001 == 73 > (即不是 0b11001000 == 200)。

所以,问题是:应如何重写下面的代码以适应上面的任务?

#include <stdio.h>

int main()
{
  long long a = 0;

  scanf("%ld", &a);

  // Here the left-shifting should be replaced with left-rotating
  printf("%ld\n", a << 1);

  return 0;
}

Let us have a task to do left-bitwise-rotation on variable a without carry in C++. I think, it would be much better to use assembly inline to perform this routine, isn't it?

For example, if we have a == 100 == 0b<a bunch of zeros>1100100, a LR 1 should provide 0b1001001 == 73 (i.e. not 0b11001000 == 200).

So, the question is: how the code below should be rewritten to fit the task above?

#include <stdio.h>

int main()
{
  long long a = 0;

  scanf("%ld", &a);

  // Here the left-shifting should be replaced with left-rotating
  printf("%ld\n", a << 1);

  return 0;
}

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

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

发布评论

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

评论(3

牵你的手,一向走下去 2024-11-07 11:49:46

带有进位的移位在高级语言(甚至 C)中毫无意义,因为除了更多的内联汇编之外,无法从此类语言中读取进位标志(以前的高位)。

另一方面,如果将高位存储到另一个变量(并且还执行移位操作),编译器可能会生成一个带有进位的移位,然后是 add-carry 或 mov-carry 来将其到达那里。编译器还相当擅长将两条指令组合成乘加融合指令。


查看您修改后的问题,您尝试执行的操作与常见处理器上可用的任何移位进位指令完全无关。由于您想要移一位,然后清除最高有效位,因此您可能会发现 bsr 指令很有帮助,许多编译器都有 内部函数,使您可以从 C 代码中访问此指令。

Shift-with-carry is meaningless in a high-level language (even C), because there's no way to read the carry flag (formerly the high bit) from such languages, except more inline assembly.

On the other hand, if you store the high bit to another variable (and also do a shift operation), the compiler may generate a shift-with-carry followed by add-carry or mov-carry to get it there. Compilers are also reasonably good at combining two instructions into multiply-add fused instructions.


Looking at your revised question, the operation you are trying to perform is completely unrelated to any shift-with-carry instruction available on common processors. Since you want to shift by one and then clear the most significant one bit, you might find the bsr instruction helpful, many compilers have intrinsic functions that give you access to this instruction from within C code.

挖鼻大婶 2024-11-07 11:49:46

进行内联汇编来完成像带有进位的左移这样简单的事情肯定不会更好。任何现代编译器都可以轻松处理该问题,并生成与您手写的任何内容等效的程序集,并且具有不依赖于平台的优点。

It would certainly not be better to do inline assembly to do something as simple as a left-shift with carry. Any modern compiler will easily handle that and produce equivalent assembly to anything you hand wrote, plus would have the advantage of not becoming as platform dependent.

无畏 2024-11-07 11:49:46

如果您确实需要汇编程序,那么以下是在 Visual C++ 中将 64 位变量左移一位的方式(对于 GCC __asm 是不同的)。为了进行比较,还有 C++ 中的实现。当然这是32位汇编器。

unsigned long long rotate_left_64(unsigned long long n)
{  
    return (n << 1) | (n >> 63);
}

int main()
{
    unsigned long long a = 0xF0F0F0F0F0F0F0F0;

    std::cout << std::hex << rotate_left_64(a) << std::endl;

    __asm
    {
        lea ebx, a
        rol DWORD PTR [ebx], 1
        rcl DWORD PTR [ebx+4], 1
    }
    std::cout << std::hex << a << std::endl;
    return 0;
}

If you really want assembler then here is how rotate left 64 bit variable by one bit might look in Visual C++ (for GCC __asm is different). For comparison there is also implementation in C++. Of course this is 32-bit assembler.

unsigned long long rotate_left_64(unsigned long long n)
{  
    return (n << 1) | (n >> 63);
}

int main()
{
    unsigned long long a = 0xF0F0F0F0F0F0F0F0;

    std::cout << std::hex << rotate_left_64(a) << std::endl;

    __asm
    {
        lea ebx, a
        rol DWORD PTR [ebx], 1
        rcl DWORD PTR [ebx+4], 1
    }
    std::cout << std::hex << a << std::endl;
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文