Question:
I'm trying to study compilers, for that I have to compile an assembly of a language called howto with nasm.
the intermediate code generated by the howto compiler is as follows:
extern printf
segment .text
align 8
global main:function
main:
segment .rodata
align 8
_L1: db 'hello', 10, 0
segment .text
mov rax, 0
mov edi, $_L1
call printf
mov rax, 0
ret
in the OSX terminal I do $ nasm -f macho out.asm
, and I have a compilation error because of the main:function
, if I remove the :function
it ends with this first error when trying to compile again. One more error, but this time it just says I should use macho64
because of the system architecture, I try to compile with $ nasm -f macho64 out.asm
and I get the error:
out.asm:11: error: Mach-O 64-bit format does not support 32-bit absolute addresses
After that I can't compile anymore, but if I use ELF64 I can create the out.o
file.
From this point with the out.o
file which I must compile with clang, I do $clang out.o -v
to return all the verbose and I get the error:
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.4.0
Thread model: posix
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.10.0 -o a.out out.o -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/lib/darwin/libclang_rt.osx.a
ld: warning: ignoring file out.o, file was built for unsupported file format ( 0x7F 0x45 0x4C 0x46 0x02 0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ) which is not the architecture being linked (x86_64): out.o
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
From this point I can't go any further, I tried to link by ld with $ ld -e _main out.o
and $ ld -e _main out.o -arch x86_64
but in these cases I get the error message:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
On linux, the compilation with $ nasm -f elf64 out.asm
went without problems in the initial form of the code and $ gcc out.o
also generated the a.out file which, when executed, returned the Hello
response of the expected message. However, as I have to finish this project on OSX, I ask the community for help.
Answer:
I'm not sure what I'm saying!!! but here it goes anyway:
The architecture of intel 80-86 and descendants is a mess!
(unlike linux) on OSX the address space exceeds 2^32 so it doesn't usually support 32-bit absolute addressing.
update : Therefore: use 64bit registers or relative address:
64-bit registers:
global main
extern puts
segment .text
main:
push rbp ; (guardar o frame pointer -- *1)
mov rax, 0
mov rdi, _L1 ; usando o registo de 64 bits corresp ao edi
call puts
pop rbp ; (retaurar o frame pointer -- *1)
mov rax, 0 ; (return 0 do C)
ret
_L1:
db "hello", 0
grades:
-
the
*1
lines are not necessary for this case but are good practice… -
I used
puts
instead ofprintf
to make it simpler
alternatively — use relative addresses (no best practices…):
global main
extern puts
segment .text
main:
mov eax, 0 ; registo de 32 bits correspondente ao rax
lea edi, [rel _L1] ; registo de 32 bits... ao rdi
call puts
ret
_L1:
db "hello", 0
Untested …I would expect these versions to work on both macho64 (OSX) and elf64 (linux). FEDERAL POLICE. tell me if it works: — I don't have 64bit machines to test