我是编写汇编代码的新手,我需要一些帮助。
我的任务是在NASM(在Linux上)编写一个程序,该程序计算第n个Fibonacci数,其中n从STDIN读取,读取系统调用并使用C atoi / atol转换为int / long。计算出的数字将写入STDOUT(我可以使用C printf)。
我设法编写了工作的32位代码,我坚持将其转换为64位(使用64位寄存器,64位长整数)。我试图天真地做(改变eax - > rax,esp - > rsp等),但我唯一得到的是段错误。
编辑:错字是固定的
EDIT2:任何想法,如何使用64位整数,显示高于第46个斐波纳契数?
以下是代码:
section .data
format: db '%d', 0xA
section .bss
buffer resb 8
bufferLength equ $-buffer;
section .text
extern printf
extern atoi
global main
main:
call fib
fib:
mov rax, 3
mov rbx, 0
mov rcx, buffer
mov rdx, bufferLength
int 0x80
push 0
push buffer
call atoi
add rsp, 8
push rbx
mov rcx, rax
xor rax, rax
xor rbx, rbx
inc rbx
call print
exitProg:
mov rbx, 0
mov rax, 1
int 0x80
print:
push rax
push rcx
push rax
push format
cmp rcx, 1
je lastPrint
add rsp, 8
pop rcx
pop rax
mov rdx, rax
mov rax, rbx
add rbx, rdx
dec ecx
jnz print
pop rbx
lastPrint:
call printf
add rsp, 8
call exitProg
提前致谢。
答案 0 :(得分:3)
您的功能不是真正的功能,因为它们不会返回。你应该考虑重写它们。如果您使用的是C库,最好从main
返回,而不是使用exit
系统调用。此外,如果允许,建议使用C库I / O函数。
在64位模式下,您通常使用syscall
指令访问系统调用,尽管int 0x80
接口也可用于兼容性。请注意,system call numbers与32位不同。
此外,即使调用约定不同(用户和系统调用),一些参数也在寄存器中传递,堆栈需要保持对齐。有关详细信息,请参阅ABI文档。
我很难理解print
代码的逻辑,特别是疯狂的堆栈操作。另请注意,永远不会到达pop rbx
行,因为rcx
之前已经检查过1
,因此在递减之后它永远不会为零。
您还有一个拼写错误bufor
。最后,您的格式字符串位于文本部分。虽然这有效,但我猜你想要它.data
,你只是错误地放置了指令(位于文件的第一行)。
我希望上面的大部分内容也适用于原来的32位代码。
更新这是一个可能的实现,现在有64位结果(最多工作n = 93)并使用XADD
(感谢Frank Kotler):
section .data
format:
db "%lu", 10, 0
section .bss
buffer resb 8
bufferLength equ $-buffer
section .text
default rel ; use rip relative addressing (optional)
extern printf
extern atoi
global main
main:
sub rsp, 8 ; stack alignment
; note: this should be a call to libc read function
; but apparently assignment forces us to use syscall
xor eax, eax ; syscall number for "read" is 0
xor edi, edi ; fd 0, stdin
lea rsi, [buffer] ; buf
mov edx, bufferLength ; length
syscall
lea rdi, [buffer]
call atoi
mov edi, eax ; pass returned value from atoi
call fib
lea rdi, [format]
mov rsi, rax ; the returned value from fib
xor eax, eax ; no xmm registers used
call printf
xor eax, eax ; return zero
add rsp, 8
ret
fib:
mov eax, edi
sub edi, 1
jle fib_done ; f(0)=0, f(1)=1
xor ecx, ecx ; f(n-1)
mov eax, 1 ; f(n)
fib_loop:
xadd rax, rcx
sub edi, 1
jnz fib_loop
fib_done:
ret