Assembly 64-bit NASM

2019-03-03 18:48发布

问题:

I am doing a proj. in 64-bit NASM. I have to convert decimal to binary and binary to decimal.

I keep getting segmentation fault after debugging when i call printf.

    extern printf

section .bss
decsave:    resd    2   ; stores dec->bin conversion
binsave:    resd    1  

section .data       ; preset constants, writeable
dec1:    db '1','2','4','.','3','7','5',0
bin1:    dq  01010110110101B ; 10101101.10101 note where binary point should be
ten:     dq     10
debug:  db "debug 124 is %ld", 10, 0

section .text       ; instructions, code segment
    global   main       ; for gcc standard linking
main:               ; label
    push    rbp             ; save rbp

;parse and convert integer portion of dec->bin     
        mov     rax,0       ; accumulate value here
        mov     al,[dec1]   ; get first ASCII digit
        sub     al,48       ; convert ASCII digit to binary
        mov     rbx,0           ; clear register (upper part)
        mov     bl,[dec1+1]     ; get next ASCII digit
        sub     rbx,48          ; convert ASCII digit to binary
        imul    rax,10          ; ignore rdx
        add     rax,rbx         ; increment accumulator
    mov rbx,0
    mov bl,[dec1+2]
    sub rbx,48
    imul    rax,10
    add rax,rbx
    mov [decsave],rax   ; save decimal portion

        mov rdi, debug
    mov rsi, [decsave]
    mov rax,0
    call    printf  

    ; return using c-style pops to return stack to correct position 
; and registers to correct content

        pop     rbp
    mov rax,0       
        ret                     ; return





; print the bits in decsave:
        section .bss
abits:  resb    17              ; 16 characters & zero terminator

    section .data
fmts:   db      "%s",0


section .text
; shift decimal portion into abits as ascii
        mov     rax,[decsave]   ; restore rax to dec. portion
        mov     rcx,8           ; for printing 1st 8 bits
loop3: mov     rdx,0           ; clear rdx ready for a bit
        shld    rdx,rax,1       ; top bit of rax into rdx
        add     rdx,48          ; make it ASCII
        mov     [abits+rcx-1],dl ; store character
        ror     rax,1           ; next bit into top of rax
        loop    loop3          ; decrement rcx, jump non zero

        mov     byte [abits+7],'.' ; end of dec. portion string
        mov     byte [abits+8],0   ; end of "C" string
        push    qword abits     ; string to print
        push    qword fmts      ; "%s"
        call    printf
        add     rsp,8

    mov     rax,[decsave+16]     ; increment to fractional portion
    mov     rcx,16       ; for printing 3 bits as required in the directions


loop4: mov     rdx,0           ; clear rdx ready for a bit
        shld    rdx,rax,1       ; top bit of rax into rdx
        add     rdx,48          ; make it ASCII
        mov     [abits+rcx-1],dl ; store character
        ror     rax,1           ; next bit into top of rax
        loop    loop4          ; decrement rcx, jump non zero

        mov     byte [abits+3],10 ; end of "C" string at 3 places
        mov     byte [abits+4],0 ; end of "C" string
        push    qword abits     ; string to print
        push    qword fmts      ; "%s"
        call    printf
        add     rsp,8

Is there a any other way to get around it?

Thank you.

回答1:

As Jester pointed out, if the vararg function is not using sse, then al must be zero. There is a bigger issue here:

With the x86-64 calling convention, parameters are not passed on the stack as they are for 32bit, but instead passed through registers. Which registers all depend on what OS your program is written for.

x86 calling conventions