如何将x86_32 nasm fibonacci更改为x86_64?

时间:2015-09-28 18:07:30

标签: assembly nasm x86-64

这是一个代码

cat fibonacci.asm 
fibonacci:
push    EBP         ; Retrieve parameter and put it
push    EBX         ; Save previous parameter
mov     EBP,ESP     ; into EBX register
add     EBP,12      ;
mov     EBX,[EBP]   ; EBX = Param

cmp     EBX,1       ; Check for base case
jle     base        ; It is base if (n <= 1)

lea ecx,[ebx-1]
push ecx            ; push N-1
call    fibonacci   ; Calculate fibonacci for (EBX - 1)
pop ecx             ; remove N-1 off the stack

push eax            ; save the result of fibonacci(N-1)
lea ecx,[ebx-2]
push ecx            ; push N-2
call    fibonacci   ; Calculate fibonacci for (EBX - 2)
pop ecx             ; remove N-2 off the stack
pop ecx             ; ecx = fibonacci(N-1)
add eax,ecx         ; eax = fibonacci(N-2) + fibonacci(N-1)

jmp end
base:               ; Base case
mov EAX,1           ; The result would be 1

end:
pop     EBX         ; Restore previous parameter
pop     EBP         ; Release EBP
ret

编译得很好

nasm -f elf -o fibonacci.o fibonacci.asm 

但未链接

ld -arch x86_64 fibonacci.o -o fibonacci_a
ld: i386 architecture of input file `fibonacci.o' is incompatible with i386:x86-64 output
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080

如何更改它并在x64 ubuntu中编译? 我真的需要这个用于测试目的:)

我也尝试了这种变化

nasm -f elf64 fibonacci_64.asm && ld -arch x86_64 fibonacci_64.o -o fab && ./fab

没有工作..

2 个答案:

答案 0 :(得分:3)

第一步:汇编程序抱怨&#34;错误:64位模式不支持指令&#34;您必须将32位寄存器更改为相应的64位寄存器,例如EBPRBP

第二步:每个PUSH现在消耗8个字节而不是4个字节。堆栈上的操作必须加倍,例如add RBP,24代替add EBP,12

第三步:不要忘记来电者,例如printfexit现在跟随&#34; System V AMD64 ABI&#34;在Linux中调用约定和在Windows中调用Windows-64调用约定。您可以在此处找到示例。

这个适用于Linux:

DEFAULT rel

section .text
GLOBAL _start
_start:

    push qword 30               ; -> 1346269
    call fibonacci
    add rsp, 8

    call write_eax

    mov edi, 0                  ; return 0 (success)
    mov eax, 60                 ; sys_exit
    syscall

fibonacci:
    push rbp
    push rbx

    mov rbp, rsp
    add rbp, 24
    mov ebx, [rbp]

    cmp     EBX,1       ; Check for base case
    jle     base        ; It is base if (n <= 1)

    lea ecx,[ebx-1]
    push rcx
    call    fibonacci   ; Calculate fibonacci for (EBX - 1)
    pop rcx

    push rax
    lea ecx,[ebx-2]
    push rcx
    call    fibonacci   ; Calculate fibonacci for (EBX - 2)
    pop rcx
    pop rcx
    add eax,ecx         ; eax = fibonacci(N-2) + fibonacci(N-1)

    jmp end
    base:               ; Base case
    mov EAX,1           ; The result would be 1

    end:
    pop rbx
    pop rbp
    ret

write_eax:
    mov rsi, rsp                ; Keyword: Red Zone (https://en.wikipedia.org/wiki/Red_zone_%28computing%29)

    sub rsi, 1
    mov byte [rsi], `\n`        ; Line feed

    mov ecx, 10                 ; Divisor

    .L1:
    xor edx, edx
    div ecx                     ; EDX:EAX / ECX -> EAX, remainder EDX
    or dl, 0x30                 ; Convert remainder to ASCII
    sub rsi, 1
    mov [rsi], dl               ; Store remainder reversed on the stack
    test eax, eax
    jne .L1

    mov rdx, rsp                ; RDX: message string length
    sub rdx, rsi
    mov rdi, 1                  ; RDI=1: stdout
    mov eax, 1                  ; sys_write
    syscall                     ; /usr/include/x86_64-linux-gnu/asm/unistd_64.h

    ret

答案 1 :(得分:2)

要在AMD64 linux上组装和链接独立程序,您可以ldd /home/taco/.rvm/gems/ruby-2.1.5/gems/nokogiri-1.6.6.2/lib/nokogiri/nokogiri.so linux-vdso.so.1 => (0x00007fff5b1fd000) libruby.so.2.1 => /home/taco/.rvm/rubies/ruby-2.1.5/lib/libruby.so.2.1 (0x00007fc4e9ae4000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc4e97de000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc4e95c5000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc4e93a7000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc4e8fe2000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc4e8dde000) libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007fc4e8ba5000) /lib64/ld-linux-x86-64.so.2 (0x00007fc4ea3f5000)

gcc -nostartfiles

yasm -f elf64 foo.asm && ld foo.o -o foo 默认的arch是本机的,即amd64。

您没有发布第二个命令行中的任何错误消息,因此IDK哪个部分出错了,或者它组装得很好,然后在运行时进行了segfaulted,因为你将64位指针截断为32位。