0

So I am taking computing machinery course in university this spring and we don't get any kind of decent assistance with assignments.

I have a program that multiplies two binary values using add-shift method which works fine for small numbers of any sign, but I need it to work with 2 certain numbers for part B of the assignment.

While debugging I have discovered that the code has the right product stored in the register but after printing the number shown is not the same as the number in the register.

Sorry if I posted too much code or didn't post enough information, please let me know if I should change anything about the post.

The code is all done through putty connecting to the school's server which is run on linux.

This is where the debugger shows that register x3 (which stores the product argument for the printf formatting) holds the right number immediately before the print statement

(gdb) i r x3
x3             0x1850505038     104426655800

This is after the print statement where it prints the wrong number

(gdb) next
50              bl      printf
(gdb) next
522133279 times 200 equals 1347440696

Here is the program

        define(multiplicand, w19)
        define(multiplier, w20)
        define(product, w21)
        define(i, w22)
        define(temp3, w23)

        define(result, x24)
        define(temp1, x25)
        define(temp2, x26)

fmt:    .string "Multiplicand: %d \nMultiplier: %d\n"
msg:    .asciz "%d times %d equals %d\n"
        .balign 4
        .global main
main:   stp     x29, x30, [sp, -16]!
        mov     x29, sp

        mov     multiplicand, 0b11111000111110001111100011111
        mov     multiplier, 0b11001000

        adrp    x0, fmt
        add     x0, x0, :lo12:fmt
        mov     w1, multiplicand
        mov     w2, multiplier
        bl      printf

        mov     i, 0
        mov     temp3, 1
loop:
        cmp     i, 32
        b.eq    print
        tst     multiplier, temp3
        b.eq    count
        uxtw    temp1, multiplicand
        uxtw    temp2, i
        lsl     temp1, temp1, temp2
        add     result, result, temp1
count:
        add     i, i, 1
        lsl     temp3, temp3, 1
        b       loop
print:
        ldr     x0, =msg
        mov     w1, multiplicand
        mov     w2, multiplier
        mov     x3, result
        bl      printf

        mov     w0, 0
        ldp     x29, x30, [sp], 16
        ret

There were no error messages

The expression i'm trying to compute is:

522133279 * 200 = 104 426 655 800

The value that printed was 1 347 440 696, but this value came from the register that had the correct value stored immediately before the print statement

Kweestor
  • 3
  • 3

1 Answers1

0
  1. 1347440696 in hex is 0x50505038
  2. 104426655800 in hex is 0x1850505038

Do you see the problem?

Make sure the formatting string (see comment) matches the data you are actually feeding to printf

Vaughan Hilts
  • 2,839
  • 1
  • 20
  • 39
  • And the solution is a format string that handles 64-bit integers, like `%lld` (`long long`), since they *are* loading a 64-bit result into `x3`. – Peter Cordes May 27 '19 at 02:45
  • Oops, thanks for pointing that out Peter. I typed this up a bit too fast and neglected the fact that I had this _backwards_ I'll revise the answer. – Vaughan Hilts May 27 '19 at 02:47
  • Thank you both, I had tried %ld but I didn't know that I should have used %lld. Thanks for the quick answers, I really appreciate that. – Kweestor May 27 '19 at 02:47
  • @Kweestor: what platform are you using where `long` is a 32-bit type on AArch64? I thought it was often equal to pointer width on most non-Windows platforms. Yup, just checked and `sizeof(long) = 8` on AArch64 Linux GCC: https://godbolt.org/z/Zyel-m. So `%ld` should be equivalent to `%lld` (both signed 64-bit integers). – Peter Cordes May 27 '19 at 02:49
  • I must have done something wrong the first time when trying ````%ld````. – Kweestor May 27 '19 at 02:54
  • @Kweestor: Probably that was an earlier version of your program that still had another bug, like maybe you were only setting `w3` at that point (which would implicitly zero-extend into `x3`). Anyway, `long long` is guaranteed to always be (at least) a 64-bit type, even in the AArch64 ILP32 ABI (32-bit pointers in 64-bit mode to save cache footprint for data structures with lots of pointers), and in practice it's not going to be *wider* than 64 bits on any AArch64 `printf`, so `%lld` or `%llu` are good choices that will always work on AArch64 for `x` registers. – Peter Cordes May 27 '19 at 02:55
  • If it's not too much to ask, i also need to complete the program using: multiplicand of -252645136, multiplier of -256 expected answer: 64 677 154 816 actual answer: -1085103631447945216 – Kweestor May 27 '19 at 03:00
  • @Kweestor You should try it on your own so you can learn. If you can't figure it out, you can open a question. – Vaughan Hilts May 27 '19 at 03:14