比特操作判断4字节DWORD中是否含有零字节

逆向理光固件里的strncpy的时候发现一种非常巧妙的比特操作,只用了一个减号、一个取反号和两个与号就能够判断一个4字节的int类型数(或者说DWORD类型)中是否有一个字节是零。记录一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
unsigned int __fastcall strncpy(unsigned int dst, char *src, unsigned int len)
{

if ( len > 3 )
aligned = (((unsigned int)src | dst) & 3) == 0;
else
aligned = 0;
not_aligned = !aligned;
dst_ = (_DWORD *)dst;
src_ = src;
if ( !not_aligned )
{
while ( 1 ) // if aligned
{
src = src_;
v14 = *(_DWORD *)src_;
src_ += 4;
tmp_4bytes = v14;
if ( ((v14 - 0x1010101) & ~v14 & 0x80808080) != 0 )
break;
len -= 4;
*dst_++ = tmp_4bytes;
if ( len <= 3 )
{
src = src_;
break;
}
}
}

注意里面if ( ((v14 - 0x1010101) & ~v14 & 0x80808080) != 0 )这个操作。

v14是一个4字节的整形数,如果其中任何一个字节是0,那么这个字节减去1之后符号位肯定会反转,之后再和0x80做与来判断每个字节的符号位是否发生了反转,来判断是否含有零。

非零的字节减去1之后符号位肯定不会反转,只有0减去1之后符号位才发生反转。