【发布时间】: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