负十六进制表示法

2024-04-26 08:35:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个问题是这样的:

 mov r15, 0x407116EF3867BBCA  
 sub r15, 0x95F67F70A1BCEE9D

What value is in r15 after this code executes?
(Be careful about integer overflow/underflows)

解决方案:用于调试的python 3数学字符串:(i64 - i64_2) % (2**64)当我按照这个公式解决这个问题时,我得到了0xaa7a977e96aacd2d

我怀疑答案应该是否定的,但我认为它已转换为2的补码。但是如果是这样的话,有什么必要把它转换成2的补码呢?那么,我的思路是否正确?如果没有,请纠正我。还有,这个公式背后的逻辑是什么(取模2^64)


Tags: inisvaluecodebethiswhat公式
1条回答
网友
1楼 · 发布于 2024-04-26 08:35:25

是的,在汇编中,64位寄存器值始终可以由16个十六进制数字表示。没有单独的加减位最好将像add/sub这样的二进制操作视为无符号的1,只需担心最终结果的2's complement解释2


这意味着使用诸如Python 3整数或^{} aka ^{}之类的任意精度计算器会稍微有点不方便,当减法运算通过0时,它们会显示负数结果,而不是像Cuint64_t那样包装

有两种方法可以考虑将结果修正为您想要的结果(在[0 .. 2**64-1]范围内):

  • 模把它缩小到那个范围这就是Python中的%所做的。(与其他一些语言(如C)或x86-64 asm中的idiv指令不同,Python%给您的是模数,总是正数,而不是余数。例如-1 % 21,但在C中,有符号int是-1

    您甚至可以手动将2**64与负数相加,以获得2的补码二进制表示形式,从而进行该缩减。因为您知道任何加法或子结果都将不小于该范围之外的2**64,所以只需要一个加法(或执行加法的减法)

  • 按位将其截断为64位,采用Python内部扩展精度2补码表示的低64位。这取决于Python在内部使用2的补码,这可能是有保证的,并且在实践中肯定是有效的(至少在Python在任何本身使用2补码的正常系统上运行时是如此)

这三种方法都给出了相同的正确结果。在交互式Python 3.9会话中:

>>> (0x407116EF3867BBCA - 0x95F67F70A1BCEE9D)
-6162446570153652947
>>> hex (0x407116EF3867BBCA - 0x95F67F70A1BCEE9D)
'-0x55856881695532d3'

>>> hex( (0x407116EF3867BBCA - 0x95F67F70A1BCEE9D) % (2**64) )
'0xaa7a977e96aacd2d'
>>> hex( (0x407116EF3867BBCA - 0x95F67F70A1BCEE9D) + 2**64 )
'0xaa7a977e96aacd2d'

>>> hex( (0x407116EF3867BBCA - 0x95F67F70A1BCEE9D) & (2**64-1) )
'0xaa7a977e96aacd2d'

另外,如果这应该是x86-64,那么sub将不会组合:只有mov可以使用64位立即数,并且0x95F67F70A1BCEE9D不适合(不能表示为)32位符号扩展立即数

但如果是这样,则会设置CF,因为高位有借出(因为0x4…-0x9…=0xa…经过零包装:减法的左侧操作数在右侧下方无符号)

和OF将被设置,因为在有符号解释中(我们将MSB视为具有- 2^63而不是+ 2^63的位置值),正数减去较大的数量级负数会产生如此大的正结果,以至于它溢出为负。(即正-负=负意味着符号溢出,就像正+正=负一样)

根据结果的MSB,SF=1


脚注1
加宽乘法和除法的高半部通常关心MSB的位值;add/sub不关心:2的补码加法是与无符号(包括环绕)相同的二进制运算。这就是为什么x86-64只有一条sub指令,但有dividiv,对于一个操作数,加宽乘法有mul与通常的imul分开。但是类似于imul eax, r9d的imul的非加宽形式对于有符号或无符号是相同的

脚注2
如果设置了高位,则如果将位模式解释为2的补码有符号整数,而不是无符号整数,则为负数。请参见Wikipedia's article about 2's complement。如果第一个十六进制数字是8到F,则设置高位,因此在本例中0x9...0xa...表示负数,而0x4...表示正数

相关问题 更多 >