转换的32位斐波那契NASM code至64位 [英] Converting 32-bit Fibonacci nasm code to 64-bit

查看:586
本文介绍了转换的32位斐波那契NASM code至64位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在编写汇编code新手,我需要一些帮助。

I'm a newbie in writing assembly code and I need some help.

我的任务是写在NASM(在Linux上),它计算第n个Fibonacci数,其中n是从标准输入读取读取系统调用,并转换为C的atoi /蒂为int /漫长的程序。计算出的号码将被写入stdout(我可以用C的printf)。

My task is to write a program in NASM (on Linux), which computes n-th Fibonacci number, where n is read from STDIN with read syscall and converted to int/long with C atoi/atol. The calculated number will be written to STDOUT (I can use C printf).

我设法写工作的32位code和我被困在将其转换为64位(使用64位寄存器,64位长整型)。我试图做到这一点天真(改变EAX - > RAX,ESP - > RSP等),但我得到的唯一的事情就是段错误

I managed to write the working 32-bit code and I'm stuck at converting it to 64-bit (using 64-bit registers, 64-bit long int). I tried to do it naively (changing eax -> rax, esp -> rsp and so on), but the only thing I get is segfault.

编辑:错字是固定

EDIT2:任何想法,如何使用64位整数,显示高于46个Fibonacci数

Any ideas, how to use 64-bit Integers, to show higher than 46-th Fibonacci number?

这里的code:

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库,这是更好的做法是从重返主力而不是使用退出系统调用。此外,它建议使用C库I / O功能,如果允许的话。

Your functions are not really functions as they don't return. You should consider rewriting them. If you are using the C library, it's better practice to return from main instead of using the exit system call. Also, it's advisable to use the C library I/O functions, if allowed.

在64位模式下,你通常访问系统调用使用系统调用指令,虽然 INT 0x80的界面也可用于兼容。注意,系统调用号是从32位不同。

In 64 bit mode, you typically access system calls using the syscall instruction, although the int 0x80 interface is also available for compatibility. Note that system call numbers are different from 32 bit.

在另外,即使在调用约定是不同的(用户和系统调用),一些参数在寄存器传递和栈需要被保持对准。详情请参阅ABI文档。

In addition, even the the calling convention is different (both user and system call), some arguments are passed in registers and the stack needs to be kept aligned. See the ABI documentation for details.

我有一个很难理解的打印 code尤其是疯狂的堆栈操作的逻辑。还要注意的是,因为 RCX 检查为是 1 流行RBX 线将永远无法实现更早,之后递减,因此它永远不会是零。

I have a hard time understanding the logic of the print code especially the crazy stack manipulations. Also note that the pop rbx line will never be reached because rcx is checked for being 1 earlier, hence after decrementing it will never be zero.

您也有一个错字, bufor 。最后,您的格式字符串文本部分。虽然这工作,我猜你想让它在。数据,你只要放错位置的指令(这是在你的文件的第一行)。

You also have a typo, bufor. Finally, your format string is in the text section. While that works, I am guessing you wanted it in .data, you just have misplaced the directive (which is on the first line of your file).

我预计上述大部分的应用到原来的32位code了。

I expect most of the above apply to the original 32 bit code too.

更新这里是一个可能的实现,现在用64位的结果(工作到N = 93),并使用 XADD (感谢Frank科特勒):

Update here is a possible implementation, now with 64 bit result (works up to n=93) and using XADD (thanks to 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

这篇关于转换的32位斐波那契NASM code至64位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆