WTF ASM

siiky

2023/04/08

2023/04/08

en

I was working yesterday on sbn and accidentally fixed digit subtraction (and consequently sbn subtraction).

../wiki/pl.c.gmi

https://git.sr.ht/~siiky/c-utils/commit/070d452f67f63868137233dcecfd820f991e36d0

Definitions needed to understand these excerpts: `sbn_digit` is `uint32_t`; `sbn_double_digit` is `uint64_t`; `sbn_double_digit_lower_half` is a macro that takes the 32 least-significant bits of a `sbn_double_digit`.

Here's the old (wrong) version:

Here's the new (fixed) version:

What's the difference? Why does one work correctly but the other doesn't? I have no clue... Obviously I expected both to be the same.

It didn't occur to me but a friend suggested taking a look at the assembly -- good idea! For some reason `gcc -S` generated a huge file like this:

No clue what this is either... So I turned to `objdump`, which was more helpful.

Here's the old (wrong) version:

Here's the new (fixed) version:

My ASM-fu was never very good but by now it's non-existent. One thing I noticed though is that on the wrong version it's using edi/eax (the 32bit registers right?), while the fixed version is using the rdi/rcx/rax (the 64bit registers right?). Is that it? But why? I can't even remember what's the arguments order: `sub X,Y` is `X-Y` or `Y-X`? `mov X,Y` is `X<-Y` or `X->Y`?