gpt4 book ai didi

assembly - 为什么有必要在被 2 的幂的有符号除法的红利中添加偏差?

转载 作者:行者123 更新时间:2023-12-04 15:11:43 24 4
gpt4 key购买 nike

我在“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
ret

What 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.


我知道编译器在这里使用了优化,创建了一个等于 x + 15 的临时变量,如果 x 小于零,则有条件地将该变量重新设置回 x。我想知道为什么首先需要使用偏见。如果代码像这样省略了前 3 个组装步骤,会发生什么?
  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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com