Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 将32位Fibonacci nasm代码转换为64位_Assembly_Segmentation Fault_X86 64_Nasm_Fibonacci - Fatal编程技术网

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

Assembly 将32位Fibonacci nasm代码转换为64位,assembly,segmentation-fault,x86-64,nasm,fibonacci,Assembly,Segmentation Fault,X86 64,Nasm,Fibonacci,我是编写汇编代码的新手,需要一些帮助 我的任务是用NASM(Linux上)编写一个程序,它计算第n个斐波那契数,其中n通过read syscall从STDIN读取,并通过C atoi/atol转换为int/long。计算出的数字将写入标准输出(我可以使用C printf) 我成功地编写了工作的32位代码,我一直在将其转换为64位(使用64位寄存器,64位长int)。我试着天真地去做(更改eax->rax、esp->rsp等等),但我得到的唯一结果是SEGFULT 编辑:打字错误是固定的 EDIT

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

我的任务是用NASM(Linux上)编写一个程序,它计算第n个斐波那契数,其中n通过read syscall从STDIN读取,并通过C atoi/atol转换为int/long。计算出的数字将写入标准输出(我可以使用C printf)

我成功地编写了工作的32位代码,我一直在将其转换为64位(使用64位寄存器,64位长int)。我试着天真地去做(更改eax->rax、esp->rsp等等),但我得到的唯一结果是SEGFULT

编辑:打字错误是固定的

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

提前感谢。

您的函数不是真正的函数,因为它们不会返回。你应该考虑改写它们。如果您使用的是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):


谢谢你指出错误。我也将格式改为.data。事实上,我只能使用C库中的atoi和printf(这是我任务的一部分)。删除计算并在64位编译的elf64可执行文件中仅使用read()+printf()(如echo)和兼容系统调用,效果非常好。@Jester感谢您展示代码。我将寄存器改为r*并放入exit()(因为我被迫使用这个系统调用)。你能告诉我,如何使用64位整数打印高于46位的斐波那契数吗?@FrankKotler我修改了代码,使用了NASM论坛的xadd示例,它可以正常工作,使代码更简单。将
fib_循环
更改为使用64位寄存器,确保将完整的64位传递给
printf
,并将格式更改为
%lu
。我将立即更新代码。感谢ASM社区委员会的
xadd
提示进入“bitRAKE”。
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