作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在“Computer Systems-A Programmer's Perspective”中学习汇编代码,遇到如下例子:
In the following C function, we have left the definition of operationOP incomplete:
#define OP
/* Unknown operator */
short arith(short x) {
return x OP 16;
}When compiled, gcc generates the following assembly code:
arith:
leaq 15(%rdi), %rax
testq %rdi, %rdi
cmovns %rdi, %rax
sarq $4, %rax
retWhat operation is OP?
The operator is ‘/’. We see this is an example of dividing by a powerof 4 by right shifting (see Section 2.3.7). Before shifting by k = 4,we must add a bias of (2^k) − 1 = 15 when the dividend is negative.
sarq $4, %rax
ret
我认为答案是我们需要从负数中去除二进制补码符号位才能得出正确的答案零。例如,如果 x = -12(即 11110100),并且我们想除以 4,那么右移 4 位而不先添加偏差将等于 11111111(或十进制形式的 -1),这不是预期的答案我期望将 -12 除以 16 的 0。相反,我们将 15 添加到 -12 得到 3(又名 00000011),然后我们可以将其右移 4 位得到 00000000,也就是 0 的正确答案十进制形式。
arith:
testw %di, %di
leal 15(%rdi), %eax
cmovns %edi, %eax
sarw $4, %ax
ret
我关于为什么需要偏见的更大问题仍然存在。是因为在没有先添加偏差的情况下移动负数会产生我提到的错误结果吗?
最佳答案
使用二进制补码表示的右算术移位负值执行整数除以 2 的幂并朝负无穷大舍入。这不是 C 中整数除法的语义,其中必须向 0 进行舍入。
为了实现 16 的有符号除法,如果它是负数,您的编译器会将分子偏置 15,并执行算术右移 4:
arith:
testw %di, %di // testing numerator
leal 15(%rdi), %eax // computing numerator+15 into %eax, flags unchanged
cmovns %edi, %eax // conditional move depending if numerator was negative
sarw $4, %ax // arithmetic right shift by 4 positions
ret
代码等价于:
short div16(short num) {
return (num < 0 ? num + 15 : num) >> 4;
}
关于assembly - 为什么有必要在被 2 的幂的有符号除法的红利中添加偏差?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65116201/
我是一名优秀的程序员,十分优秀!