Assembly NASM-seg断层中的Fibonacci
我们必须在汇编中编写代码,这一点您可能很难理解。或者教授没有给我们任何关于如何正确编码或链接的信息。我们必须自己学习。明天我得交作业。 目的是将第n个斐波那契数打印到控制台Assembly NASM-seg断层中的Fibonacci,assembly,segmentation-fault,nasm,fibonacci,Assembly,Segmentation Fault,Nasm,Fibonacci,我们必须在汇编中编写代码,这一点您可能很难理解。或者教授没有给我们任何关于如何正确编码或链接的信息。我们必须自己学习。明天我得交作业。 目的是将第n个斐波那契数打印到控制台 section .data fmt: db "fib=%d",10,0 section .text extern _printf global _main, fib _main: mov eax, 10 ; e.g. n=10 mov ebx, 1 ; we know f_0 a
section .data
fmt: db "fib=%d",10,0
section .text
extern _printf
global _main, fib
_main:
mov eax, 10 ; e.g. n=10
mov ebx, 1 ; we know f_0 and f_1
sub eax, ebx ; thats why n--
push eax ; push n
push 0 ; f_0 = 0
push 1 ; f_1 = 1
call fib
push eax ; in eax the result is stored
push fmt
call _printf
mov ebx, 0
mov eax, 1 ; exit(0)
int 0x80
fib:
mov ecx, eax
pop esi
calc:
pop ebx
pop edx
add ebx, edx
mov eax, ebx
push edx
push ebx
sub ecx, 1
cmp ecx, 0
jne calc
push esi
ret
在与链接器搏斗之后,我终于成功地组装并链接了我的程序。但它不起作用——我每次都会遇到分割错误
编辑:
更正的代码-我在控制台上看到一些文本,但遗憾的是没有正确的数字,它总是显示“fib=1”并再次显示seg fault。您有
push 0 ; f_0 = 0
push 1 ; f_1 = 1
call fib
然后
您不能这样做-call指令将在堆栈上推送返回地址,这是fib中出现的第一个问题。我不觉得汇编很难,而是觉得它简单明了。如果你的老师没有正确地教你,在网上搜索信息会对你有好处。几年前,当我们大多数人开始学习的时候,没有那么多的信息,所以我们用反复试验来学习 我建议您从简单开始,了解堆栈。将此作为工作示例:
extern printf
section .data
msg: db "Your sum is %d",10 ,0
section .text
global _start
_start:
push 20
push 2
push 6
call AddEm
push eax
push msg
call printf
add esp, 4 * 2 ; printf is C calling convention, we have to adjust stack
mov ebx, 0
mov eax, 1 ; exit(0)
int 0x80
AddEm:
push ebp ; set up a stack frame
mov ebp, esp ; we could just use esp but we won't
mov eax, [ebp + 8] ; 1st param - 6
add eax, [ebp + 12] ; 2nd param - 2
add eax, [ebp + 16] ; 3rd param - 20
mov esp, ebp ; restore the stack
pop ebp
ret 4 * 3 ; passed 3 params, clean up stack
这就是我组装、连接和输出的方式
那么,在第一行中通过pop保存值,在最后一行中通过push恢复(在ret之前)应该有效吗?有什么建议可以选择哪个寄存器进行保存吗?是的,如果有点非常规的话,那就行了——最常见的方法是按照Gunnar的建议设置堆栈框架,并将堆栈中的参数读入寄存器。暂存寄存器通常是EAX、ECX和EDX,当您返回到最外部的调用范围时,其余的寄存器通常必须保留。但是请注意,这些约定是特定于O/S的。很好的例子,下课后我会看一看。现在我将提交有缺陷的版本,我在解决链接器错误时浪费了太多时间,例如:“未解析引用”、“无法识别的格式”(当使用64位作为对象文件输出格式时)
extern printf
section .data
msg: db "Your sum is %d",10 ,0
section .text
global _start
_start:
push 20
push 2
push 6
call AddEm
push eax
push msg
call printf
add esp, 4 * 2 ; printf is C calling convention, we have to adjust stack
mov ebx, 0
mov eax, 1 ; exit(0)
int 0x80
AddEm:
push ebp ; set up a stack frame
mov ebp, esp ; we could just use esp but we won't
mov eax, [ebp + 8] ; 1st param - 6
add eax, [ebp + 12] ; 2nd param - 2
add eax, [ebp + 16] ; 3rd param - 20
mov esp, ebp ; restore the stack
pop ebp
ret 4 * 3 ; passed 3 params, clean up stack