【问题标题】:Assembly 64-bit NASM汇编 64 位 NASM
【发布时间】:2015-02-28 13:35:43
【问题描述】:

我正在做一个项目。在 64 位 NASM 中。我必须将十进制转换为二进制,将二进制转换为十进制。

当我调用 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

还有其他方法可以解决吗?

谢谢。

【问题讨论】:

  • 根据 x86-64 调用约定,varags 函数(而printf 为一)期望用于在AL 中传递的 sse 寄存器的数量。长话短说,您需要在 call printf 之前将 AL 归零。

标签: assembly 64-bit nasm


【解决方案1】:

正如 Jester 指出的,如果 vararg 函数不使用 sse,那么 al 必须为零。这里有一个更大的问题:

使用 x86-64 调用约定,参数不会像 32 位那样在堆栈上传递,而是通过寄存器传递。哪些寄存器都取决于你的程序是为什么操作系统编写的。

x86 calling conventions

【讨论】:

  • 没有注意到他也搞砸了,因为第一个 printf 正确使用了寄存器,但我稍后看到他使用了堆栈...顺便说一下,第一个调用也归零 al .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-20
  • 2012-05-29
  • 1970-01-01
相关资源
最近更新 更多