0

I tried to make a program which read 64 bit integer into two registers on RARS.

Then, when multiplying 32 bit unsigned integers by 10, I wrote

mulhu s3, s3, s2 #s2 is 10

, but s3 doesn't change form 0.

Then when I wrote

mul s3, s3, s2

it worked, but s3 is still signed integer.

The following is a part of the program.

    .eqv    SYS_EXITO, 10
    .eqv    CON_PRTSTR, 4
    .eqv    CON_PDSTR, 8
    .eqv    BUFSIZE, 100
    .data
prompt:
    .asciz  "64 bit input:"
result:
    .asciz  "64 bit addition output:"
    
buf:
    .space  BUFSIZE
    .text

main:
    la  a0, prompt
    li  a7, CON_PRTSTR
    ecall 

    la  a0, buf
    li  a1, BUFSIZE
    li  a7, CON_PDSTR
    ecall

    # processing
    la  t0, buf # t0 is the address of data (load address)
    mv  t1, t0  # t1=t0 
    li  t3, ' '
    li  t4, '0'
    li  t5, '9'
    li  s1, '1'
    li  s2, 10
    li  s3, 0 #low 32 bit1
    li  s4, 0 #high 32 bit1
    li  s5, 429496729 #4294967295 divided by 10
        
digit:
    lbu     t2,(t0)     #load t0 to t2  
    bltu    t2, t3, second  #second number if below space
    bleu    t2, t5, lessthan9   #if t2<=9, digit
    addi    t0, t0, 1   #source++
    addi    t1, t1, 1   #else destination++
    b       digit
    
lessthan9:
    bgeu    t2, t4, biggerthan0  #if t2>=0,goto digit2
    addi    t0, t0, 1   #source++
    addi    t1, t1, 1   #else destination++
    j       digit
        
biggerthan0:
    addi    t0, t0, 1   #source++
    sub     t2, t2, t4  #t2-'0'
    add     s3, s3, t2  #load to low 32 bit
    bgt     s3, s5, highfirst  #jump if s3 is bigger than 429496729
    mul     s3, s3, s2  #It works, but I want to multiply unsigned integers.
                        #So, s3 should be between 0 to 4294967295
    mulh    a2, s3, s2  #I'm not sure why s3 doesn't change from 0 
    mulh    a3, s2, s3  #Same as above
    mulhu   a4, s3, s2  #Same as above
    j       digit

So, how can I write the program which multiply unsigned integers?

  • 1
    You might consider sharing a specific numeric example perhaps cut way down to 3-4 instructions, e.g. `li t0, ?; li t1, ?; mul s0, t0, t1`, along with what values you got and what you expected/needed instead. What I'm saying is I don't think we need to analyze your whole program to answer your question, so you might help us help you with minimalization. – Erik Eidt May 19 '22 at 16:03
  • The low 32 bits of a 32x32 multiply is the same regardless of signed or unsigned. So the result of `mul` is unsigned if you want it to be. RISC-V doesn't need separate `mul` and `mulu` instructions for low-half multiplication because it uses base-2 binary integers. See [Why are signed and unsigned multiplication different instructions on x86(-64)?](https://stackoverflow.com/q/14063599) for discussion of the fact that only the high half is different. In RISC-V, that's the output of a separate instruction, unlike x86 which has widening multiply as one instruction. – Peter Cordes May 19 '22 at 16:33
  • You can see how C++ compilers do it: https://godbolt.org/z/7KM47Gbe9 - clang using`mul`, GCC using shift-and-add to do `unsigned` multiply by 10. As I suggested in my answer on your earlier question ([Could anyone help me to read 64 bit from console in 32 bit RISC-V](https://stackoverflow.com/q/72238775)), looking at compiler output for very simple functions can help you understand what it's doing for more complicated one. – Peter Cordes May 19 '22 at 16:36
  • https://stackoverflow.com/questions/71743493/behaviour-of-risc-v-mulh-assembly-instruction/71743618#71743618 – Erik Eidt May 19 '22 at 22:06
  • https://stackoverflow.com/questions/69811240/why-mulh-instruction-in-riscv32-gives-0/69813364#69813364 – Erik Eidt May 19 '22 at 22:06
  • MIPS, but still has some relevant info. https://stackoverflow.com/questions/72038539/exact-difference-between-mul-and-mulu/72046543#72046543 – Erik Eidt May 19 '22 at 22:07

0 Answers0