-1

I have the following program to multiple two numbers:

.globl main

main:
    # Store the two numbers temporarily in ebx, ecx
    mov $7,     %ebx
    mov $14,     %ecx
    # clear out eax and add ebx (7) to it ecx (14) times
    mov $0,     %eax
multiply_step:
    add %ebx,   %eax
    dec %ecx
    jnz multiply_step
    ret

However, if I add in variables for the 14 and 7 for whatever reason, the program takes about a second to run, which seems a bit strange (the above program is instantaneous) --

.globl main
.globl x,y
x:  .byte 7
y:  .byte 14

main:
    mov x,     %ebx
    mov y,     %ecx
    mov $0,     %eax
multiply_step:
    add %ebx,   %eax
    dec %ecx
    jnz multiply_step
    ret

Why does this program take longer to run? I am invoking both as:

$ gcc m2.s -o m2 && ./m2; echo $?
# 98
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
David542
  • 104,438
  • 178
  • 489
  • 842
  • 1
    You can use a debugger to see what values you get in registers; that's an easy way to get a clear picture of what's happening here. – Peter Cordes Aug 10 '20 at 04:36

1 Answers1

3

The variable x is a byte, but you are moving 4 bytes into ebx, so ebx doesn’t have the value 7. The actual value loaded into ebx is 0x1d8b0e07. Similarly, the value in ecx is something like 0x011d8b0e, so you can see why your loop takes much longer than when it is 0x0e.

Despite this error, the low byte of the result is the same.

To load these byte values into 32-bit registers, use:

movzbl x, %ebx
movzbl y, %ecx

This instruction reads a byte from memory, zero-extends it to 32 bits, and puts the result in the destination register.

Or in 64-bit code like you've been using in your other questions, RIP-relative addressing is more efficient and will work in modern PIE executables:

movzbl x(%rip), %ebx
movzbl y(%rip), %ecx
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
prl
  • 11,716
  • 2
  • 13
  • 31
  • how do you know the value in ebx is `0x1d8b0e07`, or are you just making up a number that ends with `07` ? – David542 Aug 11 '20 at 03:37
  • 1
    No, of course I would never do that! :-) I didn't get it quite right, though, because I didn't know this is 64-bit code. It should be 0x1c8b0e07. The next byte after x is y, which is 14. The next two bytes are the first two bytes of the first instruction of main, `mov x, %ebx`, which is `8b 1c 25 xxxxxxxx` in 64-bit mode, where `xxxxxxxx` is the address of `x`. (If it were 32-bit code, then it would be `8b 1d xxxxxxxx`.) – prl Aug 11 '20 at 05:25
  • awesome, thank you. Out of curiosity, how did you personally learn assembly and get so good with it? It seems like there are so many paths (unlike someone easier/mainstream like "learning python") – David542 Aug 11 '20 at 17:41