69,373
社区成员
发帖
与我相关
我的任务
分享
#include <stdio.h>
#include <stdlib.h>
unsigned int invert( unsigned int x , int p , int n );
int main()
{
printf("%u",invert( 0U , 31 , 32));
//bitset<32> s(0xffffffffU);
//printf("%u", *(unsigned *)&s);
system("pause");
return 0;
}
unsigned int invert( unsigned int x , int p , int n)
{
unsigned int r;
r = (~(~0U << n) << ( p + 1 - n));
//printf("r = %x\n",r);
unsigned s = r & x;
//printf("s = %x \n",s);
x = x | r;
x = x & (~s);
return x ;
}
r = (~(~0U << n) << ( p + 1 - n));
unsigned in i = 1;
int n = 32;
i <<= n;
上述C代码在Intel x86、PowerPC、ARM架构CPU下对应的汇编指令和移位执行说明如下:
;;Intel
;;将寄存器eax中的值左移,移动位数为寄存器cl中的值,结果存在eax中
;;仅取寄存器cl最低5 bits的值作为移位数
;;当cl寄存器中的值为32时,该操作等价于shl eax, 0,即移位操作无效
shl eax,cl
;;PowerPC
;;将寄存器RS中的值左移,移动位数为寄存器RB中的值,结果存在RA中
;;仅取寄存器RB的高6 bits作为移位数,当移位数为32-63时,移位结果为0
slw RA,RS,RB
;;ARM
;;将寄存器Rm中的值左移,移动位数为寄存器Rm中的值,结果存在Rd中
;;仅取Rs的最低8 bits作为移位数,当移位数大于31时,移位结果为0
LSL Rd, Rm, Rs
可以看到,对于C标准中未定义的操作,不同架构CPU有不同的实现和限制,导致计算结果不同。char c = 1;
int i = sizeof (int) * CHAR_BIT - 1;
c = c << i;
是未定义的吗?为什么?(char)1<<1LL
的结果是啥类型,并用汇编证明。
//32bits反转:
x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
/*circle left shift :y = (x << n) | (x >> (32 - n));
circle right shift:y = (x >> n) | (x << (32 - n));
由循环移位,第4,5句优化为:*/
x = (x << 24) | ((x & 0xFF00) << 8) |
((x >> 8) & 0xFF00) | (x >> 24);
//32b,4字节反转:
y = x & 0x00FF00FF;
(y >> 8) | (y << 24) | (((x << 8) | (x >> 24)) & 0x00FF00FF);
20: r = (~(~0U << n) << ( p + 1 - n));
00401049 or eax,0FFh
0040104C mov ecx,dword ptr [ebp+10h]
0040104F shl eax,cl
00401051 not eax
00401053 mov ecx,dword ptr [ebp+0Ch]
00401056 add ecx,1
00401059 sub ecx,dword ptr [ebp+10h]
0040105C shl eax,cl
0040105E mov dword ptr [ebp-4],eax
16:
17: unsigned int invert( unsigned int x , int p , int n)
18: {
00401040 push ebp
00401041 mov ebp,esp
00401043 sub esp,48h
00401046 push ebx
00401047 push esi
00401048 push edi
19: unsigned int r;
20: r = (~(~0U << n) << ( p + 1 - n));
00401049 or eax,0FFh
0040104C mov ecx,dword ptr [ebp+10h]
0040104F shl eax,cl
00401051 not eax
00401053 mov ecx,dword ptr [ebp+0Ch]
00401056 add ecx,1
00401059 sub ecx,dword ptr [ebp+10h]
0040105C shl eax,cl
0040105E mov dword ptr [ebp-4],eax
21:
22: //printf("r = %x\n",r);
23:
24:
25: unsigned s = r & x;
00401061 mov ecx,dword ptr [ebp-4]
00401064 and ecx,dword ptr [ebp+8]
00401067 mov dword ptr [ebp-8],ecx
26: //printf("s = %x \n",s);
27:
28: x = x | r;
0040106A mov edx,dword ptr [ebp+8]
0040106D or edx,dword ptr [ebp-4]
00401070 mov dword ptr [ebp+8],edx
29:
30: x = x & (~s);
00401073 mov eax,dword ptr [ebp-8]
00401076 not eax
00401078 mov ecx,dword ptr [ebp+8]
0040107B and ecx,eax
0040107D mov dword ptr [ebp+8],ecx
31:
32: return x ;
00401080 mov eax,dword ptr [ebp+8]
33:
34: }
00401083 pop edi
00401084 pop esi
00401085 pop ebx
00401086 mov esp,ebp
00401088 pop ebp
00401089 ret
16:
17: unsigned int invert( unsigned int x , int p , int n)
18: {
00401040 push ebp
00401041 mov ebp,esp
00401043 sub esp,48h
00401046 push ebx
00401047 push esi
00401048 push edi
19: unsigned int r;
20: r = (~(~0U << n) << ( p + 1 - n));
00401049 or eax,0FFh
0040104C mov ecx,dword ptr [ebp+10h]
0040104F shl eax,cl
00401051 not eax
00401053 mov ecx,dword ptr [ebp+0Ch]
00401056 add ecx,1
00401059 sub ecx,dword ptr [ebp+10h]
0040105C shl eax,cl
0040105E mov dword ptr [ebp-4],eax
21:
22: //printf("r = %x\n",r);
23:
24:
25: unsigned s = r & x;
00401061 mov ecx,dword ptr [ebp-4]
00401064 and ecx,dword ptr [ebp+8]
00401067 mov dword ptr [ebp-8],ecx
26: //printf("s = %x \n",s);
27:
28: x = x | r;
0040106A mov edx,dword ptr [ebp+8]
0040106D or edx,dword ptr [ebp-4]
00401070 mov dword ptr [ebp+8],edx
29:
30: x = x & (~s);
00401073 mov eax,dword ptr [ebp-8]
00401076 not eax
00401078 mov ecx,dword ptr [ebp+8]
0040107B and ecx,eax
0040107D mov dword ptr [ebp+8],ecx
31:
32: return x ;
00401080 mov eax,dword ptr [ebp+8]
33:
34: }
00401083 pop edi
00401084 pop esi
00401085 pop ebx
00401086 mov esp,ebp
00401088 pop ebp
00401089 ret