-1

Im trying to understand multiplication of two 64 bit numbers in assembly should have their results stored in rdx:rax.

chloe
  • 1
  • 2
  • What result do you expect and what result do you get? – prl Apr 26 '22 at 18:34
  • Use a debugger to single-step and look at registers change. That should help you notice when you mix up which register you're using for what (RCX vs. RBX). Also, `jump` won't even assemble, so clearly this isn't the real code you assembled and tested. The instruction is `jmp`. – Peter Cordes Apr 26 '22 at 22:10
  • hi I did. It was a typing error bt my code seems to work once I change the obvious syntax errors for 64 bit results bt it doesn't work for 128 bit results. I assumed that 128 bit result will be implicitly stored in rdx:rax as a concatenation bt im not sure. Any pointers on how to write the code for 128 bit factorial multiplication – chloe Apr 27 '22 at 08:11
  • Ask a compiler: https://godbolt.org/z/Yzq9dT4eK. 2-reg times 1-reg => 2-reg extended precision is the simplest case (other than of course 1x1 => 1 or 2 regs wide). – Peter Cordes Apr 27 '22 at 09:31
  • Hi thank you so much for the showing me the compiler method and it seems like it works properly once you translate the code into assembly bt I'm still trying to understand how it is being done. I tried to debug it to go through step by step which gives me a sense of how it is being done bt not completely. I'm new to assembly and I would like to understand how this multiplication in detail so I can try implement it myself. Is it may be possible to give like a short explanation so that I can understand the algorithm or the idea behind how the code works exactly. – chloe Apr 28 '22 at 10:35
  • Didn't see your reply since you didn't notify me with `@user`. (Only looked when you vandalized your question.) None of the x86-64 Q&As I found explained the algorithm in much detail (just fuz's answer on the first duplicate), but think about the place-values of the partial products you need. Some 32-bit answers have more theory, like [implement 64-bit arithmetic on a 32-bit machine](https://stackoverflow.com/q/11680720). If you wanted 64x64 => 128-bit on a 32-bit machine, you'd need 3 widening `mul` instructions and the high x high partial product could use `imul`. – Peter Cordes Apr 28 '22 at 12:08
  • It's the same idea as doing 2-digit by 2-digit multiplication on paper, where you write down the results of each partial product left-shifted to line up with their place value. – Peter Cordes Apr 28 '22 at 12:09
  • I just wanted to delete the question after I get a understanding of the problem because my question didn't really make any sense and I saw some similar questions like this. That's why I formatted it. Bt thanks for the explanation. I'll try to look into it.@PeterCordes – chloe Apr 28 '22 at 21:14

1 Answers1

1

The problem is here:

dec rcx
mul rcx

RCX isn't the register with the current value to multiply; RBX is the register you're using. Change to:

dec rbx
mul rbx

Also, note that you can just use RCX instead. Change the mov rbx, rdi to mov rcx, rdi instead of changing dec+mul, and now you're not destroying RBX, so you don't need to push/pop RBX.

Myria
  • 3,372
  • 1
  • 24
  • 42
  • 3
    An additional note: your code only supports a 64-bit result, except for the case 21!. Supporting a full 128-bit result (up to 34!) would be more complicated. – Myria Apr 26 '22 at 18:46
  • yes that's my problem. I have changed the code and it works for 64 bit results bt it doesn't work after that. Any pointers on how to write the code that works for 128 bit results? I assumed that implicitly 128 bit results will be stored as a concatenation in the registers rdx:rax bt it is not working – chloe Apr 27 '22 at 08:09
  • @chloe You'll need to do two multiplications. In math, `(ax + b) * c = axc + bc`. Imagine `x` as 2^64, and a and b two 64-bit numbers. a is the high half of the 128-bit number, and b is the low half. So compute `a*c` and `b*c` as 128-bit numbers, then add them together. `a*c` is shifted left by 64, so you add the low word of the result of `a*c` to the high word of the result of `b*c`. You'll need to learn the add-with-carry instruction, `adc`, to propagate carries. This, plus having to move registers around because `rax` and `rdx` are hardwired to `mul`, makes this a bit complicated. – Myria Apr 27 '22 at 18:50