Starting to learn assembly, I was given some Hello World assembly code created during the class on Linux. I would like to get it to work for 64-bit Mac OS X.
code.asm:
SECTION .data
hola: db "Hola!",10
tam: equ $-hola
SECTION .text
global main
main:
mov edx,tam
mov ecx,hola
mov ebx,1
mov eax,4
int 0x80
mov ebx,0
mov eax,1
int 0x80
This is what I do:
nasm -f macho32 -o object.o code.asm
gcc -m32 -o program object.o
Which tells me:
Undefined symbols for architecture i386: "_main", referenced from:
start in crt1.10.6.o ld: symbol(s) not found for architecture i386
Searching for this error, I found this question: nasm and gcc: 32 bit linking failed (64 bit Mac OS X)
One answer says
The problem you're having is that you're creating a 32-bit Linux(ELF)
object file which isn't compatible with the Mac OS X object format.
Try switching '-f elf' to '-f macho32'.
But I'm definitely using -f macho32. So what would the problem be then?
I've been trying to teach myself some entry-level Assembly programming too, and I ran into similar issues. I had originally compiled using nasm with elf, but that didn't work when I tried to use ld to link the object file and create the executable.
I think the answer you main question "what would the problem be then?" [to get this to run on 64bit MacOSX] is: You are using -f macho32 but expecting it to run on a 64bit machine, you need to change the command option to be -f macho64. Of course, this will not resolve the fact that your assembly code is written for a different architecture (more on that in a bit).
I found this handy answer on the right command to use in this instance to compile and link your code (after you refactor your assembly code to use the proper syntax instead of *nix as duskwuff stated): nasm -f macho64 main.asm -o main.o && ld -e _main -macosx_version_min 10.8 -arch x86_64 main.o -lSystem
After some searching, here's what I learned...
On Mac 64bit, it might be better to use the as assembler instead of nasm (if you want something more native), but if you want more portable code (learn the differences).
nasm doesn't come with the macho64 output type installed by default
Assembly is a pain in the keister (this aside)
Now that my learning rant is out of the way...
Here is the code which should operate on MacOSX 64 using nasm (if you have updated nasm with macho64, credit to Dustin Schultz):
section .data
hello_world db "Hello World!", 0x0a
section .text
global start
start:
mov rax, 0x2000004 ; System call write = 4
mov rdi, 1 ; Write to standard out = 1
mov rsi, hello_world ; The address of hello_world string
mov rdx, 14 ; The size to write
syscall ; Invoke the kernel
mov rax, 0x2000001 ; System call number for exit = 1
mov rdi, 0 ; Exit success = 0
syscall ; Invoke the kernel
Working code I used with the as assembler native to MacOSX64:
.section __TEXT,__text
.global start
start:
movl $0x2000004, %eax # Preparing syscall 4
movl $1, %edi # stdout file descriptor = 1
movq str#GOTPCREL(%rip), %rsi # The string to print
movq $100, %rdx # The size of the value to print
syscall
movl $0, %ebx
movl $0x2000001, %eax # exit 0
syscall
.section __DATA,__data
str:
.asciz "Hello World!\n"
Compile command: as -arch x86_64 -o hello_as_64.o hello_as_64.asm
Link Command: ld -o hello_as_64 hello_as_64.o
Execute Command: ./hello_as_64
Some helpful resources I found along my journey:
AS OSX Assembler Reference: https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/Assembler/Assembler.pdf
Writing 64 Bit Assembly on Mac OSX: http://www.idryman.org/blog/2014/12/02/writing-64-bit-assembly-on-mac-os-x/
Couldn't link object file using ld:
Can't link object file using ld - Mac OS X
OSX i386 SysCalls: http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/mach/i386/syscall_sw.h
OSX Master System Call Definitions: http://www.opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master
OSX Syscall: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/syscall.2.html
You would need to:
Change the label name from main to _main (in both places). Symbol naming works a little bit differently under Mac OS X.
Change the way you pass arguments to the system call. Mac OS X uses a different calling convention for the kernel from Linux; this code is not portable! I don't know as there's any official documentation for how it does work, but looking at the disassembly in GDB for a standard library function like _exit() may be instructive.
Here's _exit on my system, for instance:
<_exit+0>: mov $0x40001,%eax
<_exit+5>: call 0x96f124c2 <_sysenter_trap>
<_exit+10>: jae 0x96f10086 <_exit+26>
<_exit+12>: call 0x96f1007d <_exit+17>
<_exit+17>: pop %edx
<_exit+18>: mov 0x15a3bf9f(%edx),%edx
<_exit+24>: jmp *%edx
<_exit+26>: ret
<_exit+27>: nop
The extra bit set in 0x40001 is... weird, but can be safely ignored here.
The stuff following the call to _sysenter_trap is for error handling.
_sysenter_trap is:
<_sysenter_trap+0>: pop %edx
<_sysenter_trap+1>: mov %esp,%ecx
<_sysenter_trap+3>: sysenter
<_sysenter_trap+5>: nop
All things considered, you're probably better off linking to libSystem (the OS X equivalent of libc) instead of trying to call the kernel directly.
I've wrote a blog post on this topic: https://cs-flex.hashnode.dev/linux-assembly-on-macos
You have 3 main options:
VM -- i don't recommend
Renting a Linux server, not a bad option if you don't mind paying ~20-30$ a month
(My personal best option) using Docker to create a Linux container, that shares a folder (volume) and run assembler there. If you didn't use Docker before -- i still think this option is the best one.
You can read details in my blog post (especially if you didn't use Docker before). But in short, all you will need is this two files:
# Dockerfile
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y gcc
RUN apt-get install -y make
# docker-compose.yml
version: "3"
services:
linux:
image: linux-image
container_name: linux-container
build:
context: .
command: sleep 1000
volumes:
- .:/code
You will be able to run container and connect to it via
docker-compose up # build and run docker container
docker exec -it linux-container bash # "ssh" into container
after this you all your code in the folder with docker files will be "linked" to the folder /code/ inside `Docker. Therefore you can execute it inside docker container as if you were running Linux.
Related
As part of a class, I need to write assembly code with specific format. The teacher refers to it as "Intel syntax x86-64". I tried to compile it with the given command (gcc -O3 -o op sc.s) and despite working great on a linux PC it fails on a Mac. After some researches I found Mac OS doesn't support this syntax and following the advices from the teacher I tried to run Linux from a bootable USB key and on a Virtual Machine (using VirtualBox) but both fail due to keyboard compatibility issues. I searched a few online solution but none of them could compile the source code without problem. How can I run it without buying a new computer ? I would like to run this exact syntax if it's possible.
Thank you for reading me !
Here a exemple of code he gave us :
.intel_syntax noprefix
.data
msg: .asciz "Hello, world!\n"
.text
.global main
.type main, #function
main: PUSH RBP
MOV RBP, RSP
MOV RDI, offset flat:msg
CALL printf
MOV EAX, 0
POP RBP
RET
With can be compiled with gcc (shown in live) yet compiling it with gcc -o hw1 hw.s or gcc -o hw1 -masm=intel hw.s give me the following error :
hw.s:6:9: error: unknown directive
.type main, #function
^
hw.s:9:29: error: unknown token in expression
MOV RDI, offset flat:msg
Edit: Setting up an ssh server on the VM and connecting to the VM via the host terminal made things much easier with VirtualBox, see https://stackoverflow.com/a/10532299/5770818
I don't think there's a good solution on macOS. As far as I know, GNU binutils don't support the Mach binary format on macOS, which means you can't just use the same assembler as on Linux (gas).
The issue isn't only the syntax, in fact, the syntax as such is partially supported. You will also run into other platform-related differences. For example, the ".type" directive wouldn't be used on macOS, and symbol names are prefixed with an underscore.
If you have keyboard issues with VMs, I'd recommend setting up some server Linux distribution in the VM and then run it in headless mode. Access it by logging in with ssh. This way you interact with it through Terminal, and shouldn't have keyboard problems.
Docker might also be an option, since it actually runs Linux in a VM on macOS, but might be more work to figure out.
Anyway, if you're interested in a version of the code that works on macOS:
.intel_syntax noprefix
.data
msg: .asciz "Hello, world!\n"
.text
.global _main
_main: PUSH RBP
MOV RBP, RSP
LEA RDI, [RIP + msg]
CALL _printf
MOV EAX, 0
POP RBP
RET
I removed the ".type" line, added underscores to main and printf, and changed "MOV RDI, offset flat:msg" to "LEA RDI, [RIP + msg]".
Build with "clang -o hw1 hw1.s", no reason to pretend we're running gcc ;)
You're attempting to assemble a file using gas syntax, so you need to use an assembler that supports that -- either gas iteself, or something like yasm
I found the following code from http://www.dreamincode.net/forums/topic/328714-my-program-keeps-crashing/.
global start
;~ msvcrt.dll
extern _printf
%define printf _printf
;~ kernel32.dll
extern ExitProcess, GetCommandLineW, LocalFree
%define GetCommandLine GetCommandLineW
;~ shell32.dll
extern CommandLineToArgvW
%define CommandLineToArgv CommandLineToArgvW
SECTION .data
message db 'Hello, World', 13, 10, 0
fmtstr db "%s", 0
fmtstrCL db "Arg","%d", " = ", "%S", 13, 10, 0
section .bss
pNumArgs resd 1
section .text
start:
call GetCommandLine
push pNumArgs
push eax
call CommandLineToArgv
mov esi, eax
mov ebx, [pNumArgs]
DisplayArgs:
dec ebx
push dword[esi + 4 * ebx]
inc ebx
push ebx
push fmtstrCL
call printf
add esp, 4 * 3
dec ebx
jnz DisplayArgs
push esi
call LocalFree
push message ; Push address of "Hello, world!" onto the stack
push fmtstr ; push address of formatter onto the stack
call printf ; Print the message
add esp, 4 * 2 ; adjust stack pointer
push 0
call ExitProcess
My goal is to learn assembly language by reading other people's code and eventually write my own. I cannot figure out how to link 32-bit assembly programs on my 64-bit windows computer.
To assemble the program I use the command:
nasm -f win32 hello32.asm -o hello32.o
To link the object file I use:
gcc hello32.o -o hello32.exe
After I issue the link command I get the following error:
C:/Program Files/mingw-w64/x86_64-5.2.0-posix-seh-rt_v4-rev0/mingw64/bin/../lib/
gcc/x86_64-w64-mingw32/5.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: i386 arc
hitecture of input file `hello32.o' is incompatible with i386:x86-64 output
hello32.o:hello32.asm:(.text+0x24): undefined reference to `_printf'
hello32.o:hello32.asm:(.text+0x3f): undefined reference to `_printf'
C:/Program Files/mingw-w64/x86_64-5.2.0-posix-seh-rt_v4-rev0/mingw64/bin/../lib/
gcc/x86_64-w64-mingw32/5.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw3
2.a(lib64_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x2e): undefined refere
nce to `WinMain'
collect2.exe: error: ld returned 1 exit status
I am using 64-bit mingw binaries that are supposed to be compatible with making 32-bit programs. I have tried switching to 32-bit mingw binaries and I get a massive amount of undefined reference errors. I can link simple skeleton files without any problems using the above commands. I have no idea what I am doing wrong and I would appreciate any guidance someone could give me.
i386 architecture of input file `hello32.o' is incompatible with i386:x86-64 output
NASM has created a 32 bit object file, but you are trying to link a 64 bit executable. You could try to use the -m32 switch to create a 32 bit executable, but you already found out that this causes another bunch of errors. I do not have a solution for that either.
To link your executable, use a 32 bit MingW environment. I tried MinGW4.6.2 32 bit which worked well.
Alternatively, you can use the linker (link.exe) from a Microsoft Visual Studio installation.
https://github.com/afester/CodeSamples/tree/master/Asm/nasm_win32 shows a hello world example together with a Makefile which uses the Visual Studio linker. Alternatively, using gcc helloworld.obj -o hello32.exe from a MingW32 installation works also.
Two issues:
You're using the option -f win32 but asking for the object file in *.o extension. The two formats, .o and .obj are not compatible. But of course, you're free to specify your own extension, and so nasm will obediently assemble your code into a file with i386 arc format .o file.
Next, you're asking gcc to build that hello32.exe, using the file hello32.o. Effectively, you gave gcc an arc format .o file, and asked to build a 64-bit PE format executable out of it. And then (naturally) gcc complains:
i386 architecture of input file `hello32.o' is incompatible with i386:x86-64 output
which is correct.
Two ways you can fix this:
Assemble with: nasm -fwin32 hello32.asm and then, link with gcc -m32 hello32.obj -o hello32.exe
Assemble with: nasm -fobj hello32.asm and then link with alink -subsys console -oPE hello32.o. You can get alink from here.
Let me know which worked for you.
P.S. I have outlined the problems I have faced myself in this blog, hope that helps.
Does anyone know of any good tools (I'm looking for IDEs) to write assembly on the Mac. Xcode is a little cumbersome to me.
Also, on the Intel Macs, can I use generic x86 asm? Or is there a modified instruction set? Any information about post Intel.
Also: I know that on windows, asm can run in an emulated environment created by the OS to let the code think it's running on its own dedicated machine. Does OS X provide the same thing?
After installing any version of Xcode targeting Intel-based Macs, you should be able to write assembly code. Xcode is a suite of tools, only one of which is the IDE, so you don't have to use it if you don't want to. (That said, if there are specific things you find clunky, please file a bug at Apple's bug reporter - every bug goes to engineering.) Furthermore, installing Xcode will install both the Netwide Assembler (NASM) and the GNU Assembler (GAS); that will let you use whatever assembly syntax you're most comfortable with.
You'll also want to take a look at the Compiler & Debugging Guides, because those document the calling conventions used for the various architectures that Mac OS X runs on, as well as how the binary format and the loader work. The IA-32 (x86-32) calling conventions in particular may be slightly different from what you're used to.
Another thing to keep in mind is that the system call interface on Mac OS X is different from what you might be used to on DOS/Windows, Linux, or the other BSD flavors. System calls aren't considered a stable API on Mac OS X; instead, you always go through libSystem. That will ensure you're writing code that's portable from one release of the OS to the next.
Finally, keep in mind that Mac OS X runs across a pretty wide array of hardware - everything from the 32-bit Core Single through the high-end quad-core Xeon. By coding in assembly you might not be optimizing as much as you think; what's optimal on one machine may be pessimal on another. Apple regularly measures its compilers and tunes their output with the "-Os" optimization flag to be decent across its line, and there are extensive vector/matrix-processing libraries that you can use to get high performance with hand-tuned CPU-specific implementations.
Going to assembly for fun is great. Going to assembly for speed is not for the faint of heart these days.
As stated before, don't use syscall. You can use standard C library calls though, but be aware that the stack MUST be 16 byte aligned per Apple's IA32 function call ABI.
If you don't align the stack, your program will crash in __dyld_misaligned_stack_error when you make a call into any of the libraries or frameworks.
The following snippet assembles and runs on my system:
; File: hello.asm
; Build: nasm -f macho hello.asm && gcc -o hello hello.o
SECTION .rodata
hello.msg db 'Hello, World!',0x0a,0x00
SECTION .text
extern _printf ; could also use _puts...
GLOBAL _main
; aligns esp to 16 bytes in preparation for calling a C library function
; arg is number of bytes to pad for function arguments, this should be a multiple of 16
; unless you are using push/pop to load args
%macro clib_prolog 1
mov ebx, esp ; remember current esp
and esp, 0xFFFFFFF0 ; align to next 16 byte boundary (could be zero offset!)
sub esp, 12 ; skip ahead 12 so we can store original esp
push ebx ; store esp (16 bytes aligned again)
sub esp, %1 ; pad for arguments (make conditional?)
%endmacro
; arg must match most recent call to clib_prolog
%macro clib_epilog 1
add esp, %1 ; remove arg padding
pop ebx ; get original esp
mov esp, ebx ; restore
%endmacro
_main:
; set up stack frame
push ebp
mov ebp, esp
push ebx
clib_prolog 16
mov dword [esp], hello.msg
call _printf
; can make more clib calls here...
clib_epilog 16
; tear down stack frame
pop ebx
mov esp, ebp
pop ebp
mov eax, 0 ; set return code
ret
Recently I wanted to learn how to compile Intel x86 on Mac OS X:
For nasm:
-o hello.tmp - outfile
-f macho - specify format
Linux - elf or elf64
Mac OSX - macho
For ld:
-arch i386 - specify architecture (32 bit assembly)
-macosx_version_min 10.6 (Mac OSX - complains about default specification)
-no_pie (Mac OSX - removes ld warning)
-e main - specify main symbol name (Mac OSX - default is start)
-o hello.o - outfile
For Shell:
./hello.o - execution
One-liner:
nasm -o hello.tmp -f macho hello.s && ld -arch i386 -macosx_version_min 10.6 -no_pie -e _main -o hello.o hello.tmp && ./hello.o
Let me know if this helps!
I wrote how to do it on my blog here:
http://blog.burrowsapps.com/2013/07/how-to-compile-helloworld-in-intel-x86.html
For a more verbose explanation, I explained on my Github here:
https://github.com/jaredsburrows/Assembly
Running assembly Code on Mac is just 3 steps away from you. It could be done using XCODE but better is to use NASM Command Line Tool.
For My Ease I have already installed Xcode, if you have Xcode installed its good.
But You can do it without XCode as well.
Just Follow:
First Install NASM using Homebrew brew install nasm
convert .asm file into Obj File using this command nasm -f macho64 myFile.asm
Run Obj File to see OutPut using command ld -macosx_version_min 10.7.0 -lSystem -o OutPutFile myFile.o && ./64
Simple Text File named myFile.asm is written below for your convenience.
global start
section .text
start:
mov rax, 0x2000004 ; write
mov rdi, 1 ; stdout
mov rsi, msg
mov rdx, msg.len
syscall
mov rax, 0x2000001 ; exit
mov rdi, 0
syscall
section .data
msg: db "Assalam O Alaikum Dear", 10
.len: equ $ - msg
Also, on the Intel Macs, can I use generic x86 asm? or is there a modified instruction set? Any information about post Intel Mac assembly helps.
It's the same instruction set; it's the same chips.
The features available to use are dependent on your processor. Apple uses the same Intel stuff as everybody else. So yes, generic x86 should be fine (assuming you're not on a PPC :D).
As far as tools go, I think your best bet is a good text editor that 'understands' assembly.
Forget about finding a IDE to write/run/compile assembler on Mac. But, remember mac is UNIX. See http://asm.sourceforge.net/articles/linasm.html. A decent guide (though short) to running assembler via GCC on Linux. You can mimic this. Macs use Intel chips so you want to look at Intel syntax.
Does anyone know of any good tools (I'm looking for IDEs) to write assembly on the Mac. Xcode is a little cumbersome to me.
Also, on the Intel Macs, can I use generic x86 asm? Or is there a modified instruction set? Any information about post Intel.
Also: I know that on windows, asm can run in an emulated environment created by the OS to let the code think it's running on its own dedicated machine. Does OS X provide the same thing?
After installing any version of Xcode targeting Intel-based Macs, you should be able to write assembly code. Xcode is a suite of tools, only one of which is the IDE, so you don't have to use it if you don't want to. (That said, if there are specific things you find clunky, please file a bug at Apple's bug reporter - every bug goes to engineering.) Furthermore, installing Xcode will install both the Netwide Assembler (NASM) and the GNU Assembler (GAS); that will let you use whatever assembly syntax you're most comfortable with.
You'll also want to take a look at the Compiler & Debugging Guides, because those document the calling conventions used for the various architectures that Mac OS X runs on, as well as how the binary format and the loader work. The IA-32 (x86-32) calling conventions in particular may be slightly different from what you're used to.
Another thing to keep in mind is that the system call interface on Mac OS X is different from what you might be used to on DOS/Windows, Linux, or the other BSD flavors. System calls aren't considered a stable API on Mac OS X; instead, you always go through libSystem. That will ensure you're writing code that's portable from one release of the OS to the next.
Finally, keep in mind that Mac OS X runs across a pretty wide array of hardware - everything from the 32-bit Core Single through the high-end quad-core Xeon. By coding in assembly you might not be optimizing as much as you think; what's optimal on one machine may be pessimal on another. Apple regularly measures its compilers and tunes their output with the "-Os" optimization flag to be decent across its line, and there are extensive vector/matrix-processing libraries that you can use to get high performance with hand-tuned CPU-specific implementations.
Going to assembly for fun is great. Going to assembly for speed is not for the faint of heart these days.
As stated before, don't use syscall. You can use standard C library calls though, but be aware that the stack MUST be 16 byte aligned per Apple's IA32 function call ABI.
If you don't align the stack, your program will crash in __dyld_misaligned_stack_error when you make a call into any of the libraries or frameworks.
The following snippet assembles and runs on my system:
; File: hello.asm
; Build: nasm -f macho hello.asm && gcc -o hello hello.o
SECTION .rodata
hello.msg db 'Hello, World!',0x0a,0x00
SECTION .text
extern _printf ; could also use _puts...
GLOBAL _main
; aligns esp to 16 bytes in preparation for calling a C library function
; arg is number of bytes to pad for function arguments, this should be a multiple of 16
; unless you are using push/pop to load args
%macro clib_prolog 1
mov ebx, esp ; remember current esp
and esp, 0xFFFFFFF0 ; align to next 16 byte boundary (could be zero offset!)
sub esp, 12 ; skip ahead 12 so we can store original esp
push ebx ; store esp (16 bytes aligned again)
sub esp, %1 ; pad for arguments (make conditional?)
%endmacro
; arg must match most recent call to clib_prolog
%macro clib_epilog 1
add esp, %1 ; remove arg padding
pop ebx ; get original esp
mov esp, ebx ; restore
%endmacro
_main:
; set up stack frame
push ebp
mov ebp, esp
push ebx
clib_prolog 16
mov dword [esp], hello.msg
call _printf
; can make more clib calls here...
clib_epilog 16
; tear down stack frame
pop ebx
mov esp, ebp
pop ebp
mov eax, 0 ; set return code
ret
Recently I wanted to learn how to compile Intel x86 on Mac OS X:
For nasm:
-o hello.tmp - outfile
-f macho - specify format
Linux - elf or elf64
Mac OSX - macho
For ld:
-arch i386 - specify architecture (32 bit assembly)
-macosx_version_min 10.6 (Mac OSX - complains about default specification)
-no_pie (Mac OSX - removes ld warning)
-e main - specify main symbol name (Mac OSX - default is start)
-o hello.o - outfile
For Shell:
./hello.o - execution
One-liner:
nasm -o hello.tmp -f macho hello.s && ld -arch i386 -macosx_version_min 10.6 -no_pie -e _main -o hello.o hello.tmp && ./hello.o
Let me know if this helps!
I wrote how to do it on my blog here:
http://blog.burrowsapps.com/2013/07/how-to-compile-helloworld-in-intel-x86.html
For a more verbose explanation, I explained on my Github here:
https://github.com/jaredsburrows/Assembly
Running assembly Code on Mac is just 3 steps away from you. It could be done using XCODE but better is to use NASM Command Line Tool.
For My Ease I have already installed Xcode, if you have Xcode installed its good.
But You can do it without XCode as well.
Just Follow:
First Install NASM using Homebrew brew install nasm
convert .asm file into Obj File using this command nasm -f macho64 myFile.asm
Run Obj File to see OutPut using command ld -macosx_version_min 10.7.0 -lSystem -o OutPutFile myFile.o && ./64
Simple Text File named myFile.asm is written below for your convenience.
global start
section .text
start:
mov rax, 0x2000004 ; write
mov rdi, 1 ; stdout
mov rsi, msg
mov rdx, msg.len
syscall
mov rax, 0x2000001 ; exit
mov rdi, 0
syscall
section .data
msg: db "Assalam O Alaikum Dear", 10
.len: equ $ - msg
Also, on the Intel Macs, can I use generic x86 asm? or is there a modified instruction set? Any information about post Intel Mac assembly helps.
It's the same instruction set; it's the same chips.
The features available to use are dependent on your processor. Apple uses the same Intel stuff as everybody else. So yes, generic x86 should be fine (assuming you're not on a PPC :D).
As far as tools go, I think your best bet is a good text editor that 'understands' assembly.
Forget about finding a IDE to write/run/compile assembler on Mac. But, remember mac is UNIX. See http://asm.sourceforge.net/articles/linasm.html. A decent guide (though short) to running assembler via GCC on Linux. You can mimic this. Macs use Intel chips so you want to look at Intel syntax.
Does anyone know of any good tools (I'm looking for IDEs) to write assembly on the Mac. Xcode is a little cumbersome to me.
Also, on the Intel Macs, can I use generic x86 asm? Or is there a modified instruction set? Any information about post Intel.
Also: I know that on windows, asm can run in an emulated environment created by the OS to let the code think it's running on its own dedicated machine. Does OS X provide the same thing?
After installing any version of Xcode targeting Intel-based Macs, you should be able to write assembly code. Xcode is a suite of tools, only one of which is the IDE, so you don't have to use it if you don't want to. (That said, if there are specific things you find clunky, please file a bug at Apple's bug reporter - every bug goes to engineering.) Furthermore, installing Xcode will install both the Netwide Assembler (NASM) and the GNU Assembler (GAS); that will let you use whatever assembly syntax you're most comfortable with.
You'll also want to take a look at the Compiler & Debugging Guides, because those document the calling conventions used for the various architectures that Mac OS X runs on, as well as how the binary format and the loader work. The IA-32 (x86-32) calling conventions in particular may be slightly different from what you're used to.
Another thing to keep in mind is that the system call interface on Mac OS X is different from what you might be used to on DOS/Windows, Linux, or the other BSD flavors. System calls aren't considered a stable API on Mac OS X; instead, you always go through libSystem. That will ensure you're writing code that's portable from one release of the OS to the next.
Finally, keep in mind that Mac OS X runs across a pretty wide array of hardware - everything from the 32-bit Core Single through the high-end quad-core Xeon. By coding in assembly you might not be optimizing as much as you think; what's optimal on one machine may be pessimal on another. Apple regularly measures its compilers and tunes their output with the "-Os" optimization flag to be decent across its line, and there are extensive vector/matrix-processing libraries that you can use to get high performance with hand-tuned CPU-specific implementations.
Going to assembly for fun is great. Going to assembly for speed is not for the faint of heart these days.
As stated before, don't use syscall. You can use standard C library calls though, but be aware that the stack MUST be 16 byte aligned per Apple's IA32 function call ABI.
If you don't align the stack, your program will crash in __dyld_misaligned_stack_error when you make a call into any of the libraries or frameworks.
The following snippet assembles and runs on my system:
; File: hello.asm
; Build: nasm -f macho hello.asm && gcc -o hello hello.o
SECTION .rodata
hello.msg db 'Hello, World!',0x0a,0x00
SECTION .text
extern _printf ; could also use _puts...
GLOBAL _main
; aligns esp to 16 bytes in preparation for calling a C library function
; arg is number of bytes to pad for function arguments, this should be a multiple of 16
; unless you are using push/pop to load args
%macro clib_prolog 1
mov ebx, esp ; remember current esp
and esp, 0xFFFFFFF0 ; align to next 16 byte boundary (could be zero offset!)
sub esp, 12 ; skip ahead 12 so we can store original esp
push ebx ; store esp (16 bytes aligned again)
sub esp, %1 ; pad for arguments (make conditional?)
%endmacro
; arg must match most recent call to clib_prolog
%macro clib_epilog 1
add esp, %1 ; remove arg padding
pop ebx ; get original esp
mov esp, ebx ; restore
%endmacro
_main:
; set up stack frame
push ebp
mov ebp, esp
push ebx
clib_prolog 16
mov dword [esp], hello.msg
call _printf
; can make more clib calls here...
clib_epilog 16
; tear down stack frame
pop ebx
mov esp, ebp
pop ebp
mov eax, 0 ; set return code
ret
Recently I wanted to learn how to compile Intel x86 on Mac OS X:
For nasm:
-o hello.tmp - outfile
-f macho - specify format
Linux - elf or elf64
Mac OSX - macho
For ld:
-arch i386 - specify architecture (32 bit assembly)
-macosx_version_min 10.6 (Mac OSX - complains about default specification)
-no_pie (Mac OSX - removes ld warning)
-e main - specify main symbol name (Mac OSX - default is start)
-o hello.o - outfile
For Shell:
./hello.o - execution
One-liner:
nasm -o hello.tmp -f macho hello.s && ld -arch i386 -macosx_version_min 10.6 -no_pie -e _main -o hello.o hello.tmp && ./hello.o
Let me know if this helps!
I wrote how to do it on my blog here:
http://blog.burrowsapps.com/2013/07/how-to-compile-helloworld-in-intel-x86.html
For a more verbose explanation, I explained on my Github here:
https://github.com/jaredsburrows/Assembly
Running assembly Code on Mac is just 3 steps away from you. It could be done using XCODE but better is to use NASM Command Line Tool.
For My Ease I have already installed Xcode, if you have Xcode installed its good.
But You can do it without XCode as well.
Just Follow:
First Install NASM using Homebrew brew install nasm
convert .asm file into Obj File using this command nasm -f macho64 myFile.asm
Run Obj File to see OutPut using command ld -macosx_version_min 10.7.0 -lSystem -o OutPutFile myFile.o && ./64
Simple Text File named myFile.asm is written below for your convenience.
global start
section .text
start:
mov rax, 0x2000004 ; write
mov rdi, 1 ; stdout
mov rsi, msg
mov rdx, msg.len
syscall
mov rax, 0x2000001 ; exit
mov rdi, 0
syscall
section .data
msg: db "Assalam O Alaikum Dear", 10
.len: equ $ - msg
Also, on the Intel Macs, can I use generic x86 asm? or is there a modified instruction set? Any information about post Intel Mac assembly helps.
It's the same instruction set; it's the same chips.
The features available to use are dependent on your processor. Apple uses the same Intel stuff as everybody else. So yes, generic x86 should be fine (assuming you're not on a PPC :D).
As far as tools go, I think your best bet is a good text editor that 'understands' assembly.
Forget about finding a IDE to write/run/compile assembler on Mac. But, remember mac is UNIX. See http://asm.sourceforge.net/articles/linasm.html. A decent guide (though short) to running assembler via GCC on Linux. You can mimic this. Macs use Intel chips so you want to look at Intel syntax.