2012-05-29 38 views
-1

我们必须在大会中编写代码,正如你可能知道的那样。或者教授没有给我们提供任何有关如何正确编码或链接的信息。我们必须自己学习。明天我必须交出我的工作。 目标是将第n个斐波纳契数字打印到控制台。斐波那契在NASM - seg错误

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 

在与链接器挣扎后,我终于设法组装和链接我的程序。但它不起作用 - 我每次都会遇到分段错误。

编辑: 纠正码 - 我得到的控制台上的一些文字,但遗憾的是没有正确的号码总是显示“谎= 1”,并再次赛格故障。

回答

0

你有

push 0  ; f_0 = 0 
push 1  ; f_1 = 1 

call fib 

然后

fib: 
    mov ecx, eax 
    calc: 
    pop ebx 
    pop edx 

你不能做到这一点 - 调用指令将推动堆栈上的返回地址,这是你会被弹出的第一件事off in fib。

+0

因此节省通过弹出的数值在第一线,并通过推动恢复在最后一行(前RET)应该工作?任何建议注册选择保存? – reijin

+0

感谢您的提示 - 可悲的是我无法提出建议:/ – reijin

+0

是的,如果有点不合常规的话,它会起作用 - 最常见的方法就是像Gunnar建议的那样设置堆栈框架,并将堆栈中的参数读入寄存器。临时寄存器通常是EAX,ECX和EDX--当你返回到最外层的调用范围时,通常必须保留其余的。但请注意,这些约定是特定于O/S的。 –

0

我没有找到大会的辛苦,而是我发现它简单直接。如果你的老师没有正确地教导你,你会很乐意在互联网上搜索信息。几年前,当我们大多数人开始时,并没有那么多的信息,所以我们使用反复试验来学习。

我建议你开始简单并了解堆栈。使用这个作为一个工作示例:

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 

而这是我如何组装,链接和输出。

Screenshot

+0

很好的例子,下课后我会看一下。我现在将交付我的缺陷版本,我解决了像“无法解析的参考”,“无法识别的格式”(当使用64位作为目标文件输出格式时)解决链接器错误的时间过多, – reijin