Reputation: 1
I am stuck on some math. I'm programming in 32-bit x86 assembly, and I'm trying to figure out the difference between two numbers when the bigger number is actually smaller.
Here's an example.
Let's assume EAX is 3, and EBX is FFFFFFFE hex.
If I wanted to subtract EAX from EBX, I can easily do:
sub EBX,EAX
and I'd get the proper value of FFFFFFFB hex.
But if by chance EAX is FFFFFFFE hex, and EBX is 3 and I wanted to do subtraction, I could try:
sub EBX,EAX
But then I'd get an incorrect value with the carry set. What I would like to get is the value 5. I can't use 64-bit registers because I only have a 32-bit system to work with.
How do I go about fixing this?
I ask this because I made a tcp/ip stack and I need to keep track of data and it involves sequence numbers which never stop accumulating. When my stack sees that a file is downloading, it takes a snapshot of the sequence number at that time, then when new packets come in, the new sequence numbers are subtracted from the old.
This gets messy when the download is large enough and the sequence numbers are close to the 32-bit boundary (of FFFFFFFF hex)
Here's an example:
At start of download, say the sequence number is FFFFFF00 hex. The stack captures this number.
After 256 bytes of download, sequence number is 00000001 hex. This is messy for the stack because subtracting FFFFFF00 hex from 1 will result in a bad number with carry.
Upvotes: 0
Views: 352
Reputation: 5805
You don't need 64bit registers to calculate with more than 32 bits. Use two joined 32bit registers or two DWORD variables. Instead of
.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
define the variables as 64bit:
.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
But if by chance EAX is FFFFFFFE hex, and EBX is 3 and I wanted to do subtraction, I could try
sub EBX,EAX
But then I'd get an incorrect value with the carry set. What I would like to get is the value 5.
Similarly, when subtracting use register pairs EDX:EAX
, ECX:EBX
and instruction pair SUB
and SBB
:
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
Upvotes: 2