我正在用移位寄存器为 led 矩阵项目编程一个 arduino,我必须旋转输出值(这是一个字节),但是当我使用“<<”运算符时,它不会正确旋转该值,只是将零添加到 LSB 。
byte ilk=0b01100001;
int latch=10;
int clock=8;
int data=9;
void setup(){
pinMode(latch,OUTPUT);
pinMode(data,OUTPUT);
pinMode(clock,OUTPUT);
}
void loop(){
digitalWrite(latch,LOW);
shiftOut(data,clock,MSBFIRST,ilk);
digitalWrite(latch,HIGH);
ilk=ilk<<1;
delay(200);
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能正确地做到这一点?有没有像 ROL 这样的运算符。
我正在尝试同时处理 MSVC 和 GCC 编译器,同时更新此代码库以在 GCC 上工作。但我不确定 GCC 内联 ASM 究竟是如何工作的。现在我不太擅长将 ASM 翻译成 C,否则我只会使用 C 而不是 ASM。
SLONG Div16(signed long a, signed long b)
{
signed long v;
#ifdef __GNUC__ // GCC doesnt work.
__asm() {
#else // MSVC
__asm {
#endif
mov edx, a
mov ebx, b
mov eax, edx
shl eax, 16
sar edx, 16
idiv ebx
mov v, eax
}
return v;
}
signed long ROR13(signed long val)
{
_asm{
ror val, 13
}
}
Run Code Online (Sandbox Code Playgroud)
我假设 ROR13 …
有没有办法使用内在函数来优化以下代码?它获取 16 位整数中的所有奇数索引位,并将它们尽可能向右移动。
我在想也许可以使用 Fortran 中 IHFTC 的 C++ 等效项(是否有与此等效的 C++ 版本?)。但我觉得还有更有效的方法。
int x = some16bitInt;
x = x&0x5555;
int y = 0;
for (int i = 0; i < 8; i++)
y = y | ((x >> i) & (0x01 << i));
'''
Run Code Online (Sandbox Code Playgroud) 我试图通过仅使用按位运算符在C中实现rotateRight by n函数.
到目前为止,我已经决定使用它了.
y = x >> n
z = x << (32 - n)
g = y | z
Run Code Online (Sandbox Code Playgroud)
所以以价值为例 11010011
如果我试着`rotateRight(5):
y 变 11111110
z 变 01100000
然后g成为111111110
但是应该是正确的答案 10011110
这几乎可以工作,但问题是当我需要它来执行逻辑移位时右移复制符号位,所以我的一些答案是他们应该是什么的负面.我怎样才能解决这个问题?
注意 我无法使用强制转换或无符号类型
我曾经多次听说编译器不会优化内联汇编,或者内联汇编对它来说是一个黑盒子.我很怀疑,因为我没有看到编译器失败的任何情况,我不在乎.
但今天我在GCC维基上找到了一个名为DontUseInlineAsm的页面.它包含了人们之前告诉我的相同问题,但没有详细说明为什么编译器不理解内联asm,因此不会优化它.那么,有没有人知道编译器不做这些优化的原因?
当然,我正在收拾特殊情况
asm volatile("" : : "g"(value) : "memory"); 要么
asm volatile("" : : : "memory");
当我们明确地告诉编译器这个代码有可见的副作用时,因此它不应该优化它.
根据该参考文献和该参考文献,该shr指令支持1通过CL寄存器和立即值进行移位.但是,我似乎无法立即获得工作价值; 当我有这个代码时:
#include <stdint.h>
int main() {
uint64_t v = 15;
asm ("shr %[v], $0x04\t\n"
: [v] "+r" (v)
:
: "cc"
);
return v;
}
Run Code Online (Sandbox Code Playgroud)
我收到此错误消息:
$ gcc -masm=intel foo.c foo.c: Assembler messages: foo.c:5: Error: operand size mismatch for `shr'
如何将立即值传递给shr(不加载CL,我关心,因为我正在优化寄存器压力瓶颈).
我的EAX寄存器包含该xxxxxx9D值,并且我有以下汇编代码:
C0C8 14 --> ROR AL,14
Run Code Online (Sandbox Code Playgroud)
对我来说,这意味着EAX32 位值的最后 8 位按位旋转 14 mod 8 = 6 个位置
0x9D = b1001 1101
Run Code Online (Sandbox Code Playgroud)
将转化为
b0111 0110 = 0x76
Run Code Online (Sandbox Code Playgroud)
但是,OllyDbg 告诉我EAX = xxxxxxD9,这意味着 EAX 已按位旋转 4 位!
我哪里错了?
我有一些代码可以旋转我的数据.我知道GAS语法有一个可以旋转整个字节的汇编指令.但是,当我尝试遵循C++中循环移位(旋转)操作的最佳实践的任何建议时,我的C代码编译成至少5条指令,这些指令使用了三个寄存器 - 即使在使用-O3进行编译时也是如此.也许那些是C++的最佳实践,而不是C?
在任何一种情况下,如何强制C使用ROR x86指令来旋转我的数据?
未编译到rotate指令的精确代码行是:
value = (((y & mask) << 1 ) | (y >> (size-1))) //rotate y right 1
^ (((z & mask) << n ) | (z >> (size-n))) // rotate z left by n
// size can be 64 or 32, depending on whether we are rotating a long or an int, and
// mask would be 0xff or 0xffffffff, accordingly
Run Code Online (Sandbox Code Playgroud)
我不介意使用__asm__ __volatile__旋转,如果这是我必须做的.但我不知道如何正确地做到这一点.
从装配书:
应用于位串的另一组逻辑运算是移位和旋转操作.这两个类别可以进一步细分为左移,左旋,右移和右旋.这些操作对汇编语言程序员非常有用.
和:
另一对有用的操作是向左旋转并向右旋转.这些操作的行为类似于左移和右移操作,但有一个主要区别:从一端向外移出的位在另一端向后移位.
他们在C中的旋转操作是否等同rotate于装配中的操作?
我使用内联汇编,我的代码是这样的:
__m128i inl = _mm256_castsi256_si128(in);
__m128i inh = _mm256_extractf128_si256(in, 1);
__m128i outl, outh;
__asm__(
"vmovq %2, %%rax \n\t"
"movzwl %%ax, %%ecx \n\t"
"shr $16, %%rax \n\t"
"movzwl %%ax, %%edx \n\t"
"movzwl s16(%%ecx, %%ecx), %%ecx \n\t"
"movzwl s16(%%edx, %%edx), %%edx \n\t"
"xorw %4, %%cx \n\t"
"xorw %4, %%dx \n\t"
"rolw $7, %%cx \n\t"
"rolw $7, %%dx \n\t"
"movzwl s16(%%ecx, %%ecx), %%ecx \n\t"
"movzwl s16(%%edx, %%edx), %%edx \n\t"
"pxor %0, %0 \n\t"
"vpinsrw $0, %%ecx, %0, %0 \n\t"
"vpinsrw $1, %%edx, %0, …Run Code Online (Sandbox Code Playgroud)