【问题标题】:x86_64 intel putnbr only prints 1st number correctlyx86_64 intel putnbr 仅正确打印第一个数字
【发布时间】:2021-02-12 08:17:44
【问题描述】:

我刚开始使用 asm,正在尝试编写一些基本函数。似乎我的 write、putchar 和 putstr 工作,但我的 putnbr 打印不正确。当我尝试正数 nbr 时,它只打印第一个 nbr,而对于所有其他 nbr,它打印 0,当我打印负数 nbr 时,它打印 400000-something。我的 putchar 的代码是这样的:

BITS    64

extern  ___error
default rel

    section .bss
    buffer  resb 1       ; buffer used for character to syscall write

    section .text
    global  _ft_putchar

_ft_putchar:
    mov     [buffer], rdi    ; input char written to addres
    mov     rsi, buffer      ; address of char passed to write
    mov     rdi, 1           ; set fd
    mov     rdx, 1           ; set amount of char
    mov     rax, 0x2000004   ; set syscall
    syscall
    jc      _error
    jmp     _ret

_error:                      ; function to set errno
    push    rax
    call    ___error
    pop     qword [rax]
    mov     rax, -1

_ret:
    ret

putnbr 是递归的,我使用的逻辑与我在 C 中的 putnbr 中使用的逻辑相同:

BITS 64

extern  _ft_putchar

    section .text
    global  _ft_putnbr

_ft_putnbr:              ; function to print nbr given to it in rdi

_loop:
    xor     rax, rax     ; set rax to 0 
    cmp     rdi, 0
    jnge    _put_dash    ; if nbr < 0, write a '-' and do nbr * -1
    cmp     rdi, 10
    jnae    _put_dig     ; if nbr < 10, write the nbr
    mov     rax, 0
    mov     rax, rdi     ; put nbr in rax
    mov     rbx, 10
    mov     rdx, 0       ; set rdx to 0 (prepare for remainder div)
    div     rbx          ; devide rax by 10 put remainder in rdx
    mov     rdi, 0       ; set rdi to 0 (prepare for function call)
    push    rdi
    mov     rdi, rax     ; mov rax to rdi to do next iteration putnbr with
    call    _ft_putnbr
    pop     rdi
    mov     rdi, rdx     ; remainder div stored in rdx to rdi
    jmp     _put_dig

_put_dash:               ; subroutine for writing dash and inversing nbr
    push    rdi          ; save rdi on stack
    mov     rdi, 0
    mov     rdi, '-'     ; mov the printable char to rdi
    call    _ft_putchar
    pop     rdi          ; get rdi back from stack
    neg     rdi          ; invers nbr to positive
    jmp     _loop        ; go back to loop

_put_dig:
    add     rdi, 48      ; add 48 so nbr is ascii
    call    _ft_putchar  ; write nbr
    ret

我尝试在函数之前推送 en pop rdi,并尝试部分使用 eax 和 edi 而不是它们的四字寄存器,但我还没有找到正确的方法。希望大家能发现错误!

【问题讨论】:

  • 每个人都喜欢调试数英里未记录和未注释的汇编代码。尝试添加一些 cmets 来表明你认为你的代码在做什么。这样,发现错误会更愉快。另外,请告诉我们您正在为什么操作系统编程。
  • 我还假设nbr 是“数字”的缩写?那么putnbr 是您的号码打印程序吗?
  • 好的,我会添加 cmets。我意识到这样会很难阅读
  • 第一个清除错误:mov [buffer], rdi 移动了 8 个字节,因为 rdi 是一个 64 位寄存器,但 buffer 的空间只有 1 个字节。确保您了解操作数大小的概念,对于新的汇编程序员来说,这是一个常见的绊脚石,因为高级语言会为您处理它。你可以用mov [buffer], dil代替只对8位寄存器dil进行操作,这是rdi的低字节。
  • 你还没有说它是用于什么操作系统的。它看起来像 MacOS,但请将此添加到问题中。

标签: assembly printing numbers x86-64 nasm


【解决方案1】:

非常感谢 Nate,问题确实是我在调用 ft_putnbr 而不是 rdx 之前推送了 rdi。 所以在调用rdx被重置之后,我只是将一个0复制到rdi到putchar。 本段:

    push    rdi
    mov     rdi, rax     ; mov rax to rdi to do next iteration putnbr with
    call    _ft_putnbr
    pop     rdi

应该是:

    push    rdx
    mov     rdi, rax     ; mov rax to rdi to do next iteration putnbr with
    call    _ft_putnbr
    pop     rdx

我也会更改我的 putchar,虽然这一直有效,但我知道这是不好的做法

【讨论】:

    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 2013-02-08
    • 2021-05-11
    • 1970-01-01
    • 2015-08-15
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    相关资源
    最近更新 更多