0

I’m reading a book on how to program in assembly using NASM and having problem building a program that print 3.1400000.

Code might have a few problems like, using wrong statement in section .data pi: .float 3.14 should be of type double quad but I have no idea which pseudo-op maps to that; I tried .dq however doesn’t works like that.

Also i’ve read that call stack need to be align before programs start, I hope that using base pointer solves that problem otherwise without program prints a segment error.

One other note for learning purposes i’m using GAS with Intel syntax hence i’m not sure syntax mapping below is correct.

Code:

#fmtflt.s
.intel_syntax noprefix
.extern printf 

.section .data
    pi: .float 3.14

.section .rodata
    fmtflt: .ascii  "%1f\12\0"

.section .text
    .globl main
        main:
            push    rbp
            mov     rbp, rsp
            mov     rax, 0             # set total numers xmm register  
            movq    xmm0, [pi]          # set content pi to
            mov     rdi, offset fmtflt  # set address format string
            call    printf              # call printf function
            mov     rsp, rbp
            pop     rbp
            ret

Compile: gcc -no-pie -o fmtflt fmtflt.s

Output:

actual: 0.000000
expected: 3.140000

Can anyone fill in missing piece such that program prints expected output ?

1 Answers1

1

using wrong statement in section .data pi: .float 3.14 should be of type double quad but I have no idea which pseudo-op maps to that;

Use .double to assemble an 8-byte double-precision floating point value. See https://sourceware.org/binutils/docs/as/i386_002dFloat.html#i386_002dFloat.

Then, as Joseph points out, look at the line:

mov     rax, 0             # set total numers xmm register  

As the comment says, rax should be set to the total number of xmm (SSE) registers being used to pass arguments. See Figure 3.4 of the x86-64 SysV ABI, which is the authoritative reference for calling conventions on systems like Linux that use it. You are passing 1 argument in an xmm register (on the very next line), so set rax to 1, not 0. The instruction mov eax, 1 has the same effect (because moves into 32-bit registers zero the upper half of the 64-bit register) and is one less byte.

With those changes, the program correctly prints 3.140000 for me.

Also i’ve read that call stack need to be align before programs start, I hope that using base pointer solves that problem otherwise without program prints a segment error.

Yes, you got that part right.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82