This is an implementation of the TCP/IP checksum computation as described in https://www.rfc-editor.org/rfc/rfc1071.
The function is writen in DynASM, an assembler preprocessor that is part of LuaJIT. I didn't use much of the fancy stuff of DynASM so pretty much it looks like native X86_64 I think.
-- Prologue. | push rbp | mov rbp, rsp -- Accumulative sum (16-bit). | xor r9, r9 -- Clear out r9. Stores accumulated sum. | mov rcx, 0 -- Set index to 0. | 1: | cmp rcx, rsi -- Rsi stores size arg. Compare index to size. | jg >2 -- Go to branch '2' if equals. | mov ah, [rdi + rcx] -- Read 16-bit of data and swapping byte order. | mov al, [rdi + rcx+1] | add r9, rax -- Sum and accumulate into r9. | add rcx, 2 -- Increase index by 2. | jmp <1 -- Go to beginning of loop. | 2: | mov rax, r9 -- Save accumulated sum in rax. -- Sum carry until done. | 4: | shr r9, 16 -- Right-shift r9 16-bit to obtain value of carry. | cmp r9, 0 -- Check whether there's carry. | jz >5 -- In case not, go to '4'. | and rax, 0xffff -- Clear out higher part of rax. | add rax, r9 -- Sum carry to rax. | mov r9, rax -- Assign rax to r9 to check if there's carry again. | jmp <4 -- Go to beggining of loop. -- One-complement. | 5: | not rax -- One-complement of rax. | and rax, 0xffff -- Clear out higher part of rax. -- Epilogue. | mov rsp, rbp | pop rbp -- Return. | ret
I verified against a Lua implementation the result is correct. I was wondering if I could write the code in a different way to use less instructions. For instance, the RFC says it's possible to sum the octets as a dword. I tried but I didn't manage to get a correct checksum.