给出以下简短的汇编代码片段:

shr   rax, 3
adc   rax, 0


我做了以下工作:


我们知道SHR将CF设置为最后一位移位了。
我们知道ADC dest, 0只是添加了CF。

所以,看看这些位,

        128  64  32  16  8   4   2   1 
        8    7   6   5   4   3   2   1
        ------------------------------
        1    1   1   1   1   CF  X   X
CF=1 |  0    0   0   1   1   1   1   1  ; shr 3


所以如果我们在div 8上添加CF,那么最正确的功能就是这样,

快速测试一下,我可以看到我是对的。

def f(x):
  return x//8  + int( (x//4) % 2 )


用Radare反编译在这里也没有用,

rax = 0  -> 0
rax = 1  -> 0
rax = 2  -> 0
rax = 3  -> 0

rax = 4  -> 1
rax = 7  -> 1
rax = 8  -> 1
rax = 11 -> 1

rax = 12 -> 2
rax = 13 -> 2
rax = 14 -> 2
rax = 15 -> 2
rax = 16 -> 2
rax = 17 -> 2
rax = 18 -> 2
rax = 19 -> 2

...

rax = 20 -> 3
rax = 28 -> 4

我确实理解这些指令对操作数寄存器的直接影响,该指令序列的高级含义是什么? br />

评论

xchg rax,rax的谜题的确不错。不过这里有问题吗?

@NirIzr是的,很显然谜语的答案是什么? “谜语”表示它正在尝试演示或做某事,或者具有某种实用性,并且背后有意图。 CPU可以执行的任何两条指令都会做某事(即使只是浪费时间),为什么选择这两条指令呢?

我已经弄清楚了代码在机器中的作用,但是它的用途是什么?它可以用来做哪些有用的高级操作?

请在标题而非书名中加上您要查询的内容(shr和adc放在同一寄存器中)。问题正文中的书名足以使搜索工作正常。

#1 楼

shr rax, 3是一个无符号除以8,并被截断为零。 adc rax, 0的加入使除法舍入到最接近的值。 (尽管0.5总是四舍五入)

因此,如果RAXRAX[4-11])范围内,则此操作会将8*1 ±4设置为


1。 > 2,如果RAX[12-20]8*2 ±4)的范围内
3如果RAX[20-27]8*3 ±4)的范围内

您可以通过将偏移减小到1来进一步简化此操作。 br />
mov rax, 47  ; (remember 47/2 is 23.5)
shr rax, 1   ; rax = 23
adc rax, 0   ; rax = 24


如果再做一次,

mov rax, 46  ; (remember 46/2 is 23)
shr rax, 1   ; rax = 23
adc rax, 0   ; rax = 23


评论


这就是正在发生的事情。我曾考虑过截断为零和舍入的情况。但是我没有考虑最近的情况。

–埃文·卡洛尔(Evan Carroll)
18-10-26在19:41