Compile Linux-ready Assembly on OSX

Asked

Viewed 195 times

5

I’m trying to do a study of compilers, so 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

at the OSX terminal do $ nasm -f macho out.asm, and I have build error because of main:function, if you remove the :function ends with this first error when trying to compile again. Another 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’m wrong:

out.asm:11: error: Mach-O 64-bit format does not support 32-bit Absolute Addresses

After this I can no longer compile, but if I use ELF64 I can create the file out.o.

From this point with the file out.o which I must compile with the Clang, I do $clang out.o -v to return all the verbose and 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 receive 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

In linux the compilation with $ nasm -f elf64 out.asm was without problems of the initial way of the code and the $ gcc out.o also generating the.out file that when running returned the answer Hello of the expected message. However, as I have to finish this project in OSX, I ask the community for help.

2 answers

1

I’m not sure what I’m saying!!! but here goes anyway:

Intel 80-86 architecture and descendants is a mess!

(unlike linux) in OSX the address space exceeds 2 32 so it usually does not support 32-bit absolute addressing.

update: Therefore: use 64bit or relative records:

64-bit logs:

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

notes:

  • the lines *1are not necessary for this case but are a good practice...

  • used puts instead of the printf to make it simpler

alternatively -- use relative addresses (good practice-free...):

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). PF. tell me if it works: -- I don’t have 64bit machines to test

  • Nothing certain, generates error out.asm:12: error: invalid operand size specification. In this case I added to the beginning of the document default rel and as requested I put in place of move edi, $_L1 the rel to stay move edi, rel $_L1.

  • @Thiagoprado -- I wrote my solution attempt. You can check if it works and if it makes sense?

  • So @Jjoao, sorry for the delay to check, however I was unsuccessful, in the case of your first example when compiling I got the return of the message: Undefined symbols for architecture x86_64:
 "_main", referenced from:
 implicit entry/start for main executable
 "puts", referenced from:
 main in alt02.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation). The second example also had a similar error. All examples I tried to compile with nasm -f macho file.asm and nasm -f macho64 file.asm.

  • @Thiagoprado, let’s see step by step: 1) nasm -v (to check the version) 2) nasm -f macho64 file.asm (made mistakes? ) 3) cc file.o (error) 4) ./a.out

  • Let’s go then. 1) NASM version 2.11.08 Compiled on Mar 10 2015, soon last version of the Brew repositories. 2) Here ok, creates the file . o without problems and errors and without messages. 3) Undefined symbols for architecture x86_64:
 "_main", referenced from:
 implicit entry/start for main executable
 "puts", referenced from:
 main in alt02.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation). This is the error when compiling with cc.

  • To help the version of my Clang 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.

Show 1 more comment

0

As per this post in the OS in English:
https://stackoverflow.com/questions/13091987/x64-nasm-pushing-memory-addresses-onto-the-stack-call-function

The address of the message 'hello' must be related to.

And, as this post here:
https://stackoverflow.com/questions/14696320/trouble-linking-printf-and-scanf-in-assembly-x86-64-and-c-file-on-mac-osx

Functions are prefixed by an underline '_'.

Therefore, the function main should be amended to _main (programme entry point), as well as the printf, changed to _printf.

The recorder rbp must be saved to avoid a segmentation error.

Below, follow the program already with the changes:

        extern _printf
        global _main

_main:

segment .rodata

        align 8

_L1:    db 'hello', 10, 0

segment .text

        push rbp          

        mov rax, 0
        lea rdi, [rel _L1]
        call _printf
        mov rax, 0

        pop rbp
        ret

To compile:

nasm -f macho64 out.asm

Link:

clang out.o

Below, the output of execution:

$ ./a.out
hello
$ 

Compiled with NASM version 2.11.08 in a system OS X El Capitan.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.