0

I'm rolling off my own TCP/IP stack. The network byte ordering is different from the PC byte ordering, and I see this when I run tests on my own stack with linux tcpdump.

If I take a 16-bit network value and I want to increment the original value by 1, I could use this kind of code (in all cases, networkvalue is declared as a double-word):

mov AX,[CS:networkvalue]
xchg AL,AH
inc AX
xchg AL,AH
mov [CS:networkvalue],AX

But how would I do it with a 32-bit value successfully? Because this kind of code:

mov EAX,[CS:networkvalue]
inc EAX
mov [CS:networkvalue],EAX

does not work properly.

The reason why I ask this is because I want to take the sequence number of a remote packet, increment it then send it out as an acknowledgement and both values are 32-bit.

The only thing I can come up with off the top of my head is this, but I might be off:

mov BL,[CS:networkvalue]
mov BH,[CS:networkvalue+1]
mov CL,[CS:networkvalue+2]
mov CH,[CS:networkvalue+3]
mov [CS:networkvalue],CH
mov [CS:networkvalue+1],CL
mov [CS:networkvalue+2],BH
mov [CS:networkvalue+3],BL
mov EAX,[CS:networkvalue]
inc EAX
mov [CS:networkvalue],EAX
mov BL,[CS:networkvalue]
mov BH,[CS:networkvalue+1]
mov CL,[CS:networkvalue+2]
mov CH,[CS:networkvalue+3]
mov [CS:networkvalue],CH
mov [CS:networkvalue+1],CL
mov [CS:networkvalue+2],BH
mov [CS:networkvalue+3],BL

Any idea how I can solve my issue?

And I would prefer an answer that would work with older (say 386' or 486' model PC's) because I'm making networking software for an older popular game.

  • 1
    Didn't BSWAP do this? IIRC, it was i486. – David Wohlferd May 04 '21 at 05:43
  • @DavidWohlferd: Yup, https://www.felixcloutier.com/x86/bswap confirms memory that it was new in 486. Without that, you could consider `add byte [mem+3], 1` / `adc [mem+2], 0` / etc to propagate carry, but that's probably even worse than emulating bswap both ways with 3x `rol` (word/dword/word). Maybe there's some middle ground micro-optimization, if anyone cares about running on 386 while not being horrible on later CPUs. – Peter Cordes May 04 '21 at 06:32
  • Your 16-bit version should use `rol ax, 8` - probably about equal on 386 (which has a barrel shifter), and faster on later CPUs (Pentium Pro / P6- family) where it avoids partial-register stalls when you read AX after writing AL and AH. – Peter Cordes May 04 '21 at 06:36
  • 1
    For byte swapping 32 bit numbers on a 386, you can do something like `xchg ah, al; rol eax, 16; xchg ah, al`. – fuz May 04 '21 at 08:23
  • 1
    Packets do not have sequence numbers or acknowledgements (neither IPv4 nor IPv6). TCP segments have sequence numbers and acknowledgements, but packets know nothing about that. A TCP acknowledgement number is the number of the next expected data byte and acknowledges everything prior to the number, and blindly incrementing a received sequence number to acknowledge is the incorrect thing to do. You may receive segments out of order, and your method could acknowledge segments not yet received. You must track what has or has not been received and know what is expected. – Ron Maupin May 04 '21 at 10:03
  • 1
    I really do not know what OS on your 386/486 PCs did not have an IP network stack. We ran DOS, Windows 3.1, 95, 98, 2000, etc. on 386/486 and had networks stacks for all of them. TCP is very complicated, and you must be intimately familiar with RFC 793 and all the subsequent updates and congestion standards since that RFC was published. – Ron Maupin May 04 '21 at 10:07
  • A little note:`ROL` affects `CF` and makes `OF` be undefined. `XCHG` and `BSWAP` don't affect flags. – W. Chang May 04 '21 at 14:29

0 Answers0