问题描述
我在编写汇编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位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!