将32位Fibonacci-nasm代码转换为64位



我是编写汇编代码的新手,需要一些帮助。

我的任务是用NASM(在Linux上)编写一个程序,它计算第n个Fibonacci数,其中n用read syscall从STDIN读取,并用C atoi/atol转换为int/long。计算出的数字将被写入STDOUT(我可以使用C printf)。

我设法编写了可工作的32位代码,但我一直无法将其转换为64位(使用64位寄存器,64位长的int)。我试着天真地去做(改变eax->rax,esp->rsp等等),但我得到的只有segfault。

编辑:打字是固定的

第二版:有什么想法,如何使用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

提前谢谢。

您的函数并不是真正的函数,因为它们不会返回。你应该考虑重写它们。如果您使用的是C库,最好从main返回,而不是使用exit系统调用。此外,如果允许,建议使用C库I/O函数。

在64位模式下,通常使用syscall指令访问系统调用,尽管int 0x80接口也可用于兼容性。请注意,系统呼叫号码不同于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

相关内容

  • 没有找到相关文章

最新更新