这是一个代码
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
没有工作..
答案 0 :(得分:3)
第一步:汇编程序抱怨&#34;错误:64位模式不支持指令&#34;您必须将32位寄存器更改为相应的64位寄存器,例如EBP
至RBP
。
第二步:每个PUSH
现在消耗8个字节而不是4个字节。堆栈上的操作必须加倍,例如add RBP,24
代替add EBP,12
。
第三步:不要忘记来电者,例如printf
和exit
现在跟随&#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位。