0

Trying simple mul instruction, where the result is stored in edx-eax registers:

    section .data
    a dd 315814
    b dd 165432
    result dq 0
    format db 'The result is %d', 10

    section .text
    extern printf
    global main

main:
    mov eax, [a]
    mul dword [b]
    mov [result], eax
    mov dword [result + 4], edx
    
    sub rsp, 8
    mov rdi, format
    mov rsi, qword [result]
    call printf

    xor rdi, rdi
    mov rax, 60
    syscall

The final value is only taken from the eax register (in other words, the mov dword [result + 4], edx seems to have no effect. The output:

The result is 706134096

but should be 52,245,741,648. So what do I do wrong?

milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • 1
    You told printf to only look at a `%d` `int` value, not a `long int` `%ld`, so it's required to ignore high "garbage" in RSI above ESI. – Peter Cordes Feb 15 '22 at 17:44
  • 1
    Also, the normal way to do this would be `mov eax, [a]` / `mov esi, [b]` / `imul rsi, rax` when you want a 64-bit result on x86-64, rather than using legacy widening `mul` and having to deal with two halves. And don't use a raw `_exit` syscall after stdio functions; if you redirect stdout, it'll be full-buffered so you'll get no output if you don't `ret` or `call exit` to trigger flushing of buffers. And don't forget to explicitly 0-terminate your format string; printf is reading one byte past the `, 10` to find a 0 terminator. – Peter Cordes Feb 15 '22 at 17:46
  • 1
    Also, don't forget to zero AL to tell printf how many FP args are in SSE registers (0). It still happens to work the way modern GCC compiler (just testing for 0 / non-0 instead of a computed jump) even if AL is outside the 0..8 range, but it still violates the ABI on paper. – Peter Cordes Feb 15 '22 at 17:54

0 Answers0