滚动时两个无符号变量之间的差异



我有些数学问题。我在32位x86汇编中编程,当较大的数字实际上较小时,我试图找出两个数字之间的差异。

下面是一个例子。

假设EAX是3,EBX是FFFFFFF E十六进制。

如果我想从EBX中减去EAX,我可以很容易地做到:

sub EBX,EAX

我会得到FFFFFFF B十六进制的正确值。

但如果碰巧EAX是FFFFFFF E十六进制,EBX是3,我想做减法,我可以尝试:

sub EBX,EAX

但是,我会得到一个不正确的值与进位集。我想要的是数值5。我不能使用64位寄存器,因为我只能使用32位系统。

我该怎么解决这个问题?

我问这个问题是因为我制作了一个tcp/ip堆栈,我需要跟踪数据,它涉及到永远不会停止累积的序列号。当我的堆栈看到一个文件正在下载时,它会对当时的序列号进行快照,然后当新的数据包进来时,会从旧的序列号中减去新的序列号。

当下载量足够大并且序列号接近32位边界(FFFFFFFF十六进制(时,这会变得很混乱

这里有一个例子:

在下载开始时,假设序列号是FFFFFF 00十六进制。堆栈捕获这个数字。

下载256字节后,序列号为00000001十六进制。这对堆栈来说是混乱的,因为从1减去FFFFFF 00十六进制将导致带进位的坏数字。

您不需要64位寄存器来计算超过32位的值。使用两个连接的32位寄存器或两个DWORD变量。代替

.data
Sequence DD 0xFFFFFF00
Download DD 0x00000100
.code
MOV EAX,[Sequence]  ; EAX=FFFFFF00
MOV EBX,[Download]  ; EBX=00000100
ADD EAX,EBX         ; EAX=00000000, CF=1

将变量定义为64位:

.data
SequenceLo DD 0xFFFFFF00
SequenceHi DD 0x00000000
DownloadLo DD 0x00000100
DownloadHi DD 0x00000000
.code
MOV EAX,[DownloadLo]  ; EAX=0x00000100
MOV EDX,[DownloadHi]  ; EDX=0x00000000
ADD [SequenceLo],EAX  ; [SequenceLo]=0x00000000, CF=1
ADC [SequenceHi],EDX  ; [SequenceHi]=0x00000001, CF=0

但如果碰巧EAX是FFFFFFF E十六进制,EBX是3,并且我想做减法,我可以尝试sub EBX,EAX,但我会用进位集得到一个不正确的值。我想得到的是值5。

类似地,减法时使用寄存器对EDX:EAXECX:EBX以及指令对SUBSBB:

MOV EAX,0xFFFFFFFE
CDQ                 ; EDX:EAX=0xFFFFFFFF:0xFFFFFFFE
MOV EBX,0x00000003
XOR ECX,ECX         ; ECX:EBX=0x00000000:0x00000003 
SUB EBX,EAX         ; ECX:EBX=0x00000000:0x00000005, CF=1
SBB ECX,EDX         ; ECX:EBX=0x00000000:0x00000005, CF=0 

最新更新