movsbl (%rax, %rcx, 1),%eax和$0xf, %eax做什么?


movsbl (%rax, %rcx, 1),%eax
and $0xf, %eax

我:

%rax=93824992274748
%eax=1431693628
%rcx=0

我真的不知道为什么我有这些结果:第一条指令是怎么得到%eax=97的?为什么在二进制表示的971111之间的and得到的是1?

按位与运算比较两个操作数的位。在本例中,97 AND 15:

0110 0001  ;97
0000 1111  ;15

对于每一列位,如果列中的两位都为1,则该列的结果位为1。否则为0。

0110 0001  ;97
0000 1111  ;15
---------------
0000 0001  ;1

您可能想知道这是什么目的。实际上,你可以用AND做很多事情,其中很多第一眼看起来并不明显。将其中一个操作数视为数据,另一个操作数视为"过滤器",这很有帮助。


例如,假设我们有一个名为rand的函数,每次调用它时都会在%eax中返回一个随机的32位无符号整数。假设所有可能的值都是等可能的。现在,假设我们有一个叫做myEvent的函数,我们是否调用它取决于rand的结果。如果我们希望这个事件发生的几率是1/16,我们可以这样做:

call rand
and $0xf, %eax
jnz skip
call myEvent
skip:

之所以有效是因为16的每个倍数都有底部4位清除。所以这些是我们唯一感兴趣的位,我们可以使用and $0xf, %eax忽略这4位左边的所有内容,因为它们在and之后都会变成零。一旦我们完成了and,我们就可以看到%eax是否包含零。如果是,则%eaxand之前包含16的倍数。


下面是另一个例子。这告诉你%eax是奇数还是偶数:

and $1, %eax
jnz isOdd

如果一个数字最右边的二进制数字是1,那么这个数字就是奇数。任何时候在高级语言中执行n % 2,编译器都会将其替换为n & 1,而不是执行实际的除法。

最新更新