how to make .O from .ASM on mac - macos

I have the following file hello.asm:
section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!', 0xa ;our dear string
len equ $ - msg ;length of our dear string
On mac, how would i turn it into a .o file. On linux i would do
nasm -f elf64 -o hello.o hello.asm
ld -o hello hello.o
then it could be called with
./hello
I have already installed Xcode and MacPorts, Thanks

Using:
nasm -o hello.o hello.asm
should work, that is, to produce an .o file. typically on OS X you do something such as:
nasm -f macho -o hello.o hello.asm

Related

How do I compile assembly?

The problem is that I have a filesystem in documents/assembly that goes like this:
test.s:
.global _start
.text
_start:
mov $60, %rax # exit
mov $0, %rdi # return code 0
syscall
test.o:
\* exists \*
compile.bash:
as -o test.o test.s && ld -e _start -o test.s test.o && chmod 777 test.o && (./test ; echo $?)
But when I try running compile.bash I get:
ld: dynamic executables or dylibs must link with libSystem.dylib for architecture x86_64
And when I try running test.o:
bash: ./test.o: cannot execute binary file
I'm using gnu assembler, But instead of gcc in the tutorial I say as.
I tried changing the command, But what happened was that it gave a lot of errors. I'm using macos monetary version 12.5.1 (21G83). What I expected was it to print 0 when running the command, But it didn't.

Is there any reference to "main" in the default linker scripts of arm-none-eabi that could interfere when linking from the command line

When using the gnu toolchain particularly arm-none-eabi is there any reason why when using the command line linker option it resorts to what seems an incorrect address to the start of 'main'. However, when 'main' is anything else the correct starting address and stack is initialized. For example,
.thumb
.syntax unified
.globl _start
_start:
.word 0x20001000
.word reset
reset:
bl main
b .
int main ( void )
{
return(0);
}
arm-none-eabi-gcc -O2 -c -mthumb main.c -o main.o
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c -mthumb main.c -o main.o
arm-none-eabi-ld -Ttext=0x08000000 start.o main.o -o main.elf
arm-none-eabi-objdump -d main.elf
main.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <main>:
8000000: 2000 movs r0, #0
8000002: 4770 bx lr
08000004 <_start>:
8000004: 20001000 .word 0x20001000
8000008: 0800000c .word 0x0800000c
0800000c <reset>:
800000c: f7ff fff8 bl 8000000 <main>
8000010: e7fe b.n 8000010 <reset+0x4>
in the disassembly the output above doesn't initialize the stack 0x20001000 and start of rom 0x08000000 correctly from what I notice, but..
.thumb
.syntax unified
.globl _start
_start:
.word 0x20001000
.word reset
reset:
bl notmain
b .
int notmain ( void )
{
return(0);
}
arm-none-eabi-gcc -O2 -c -mthumb main.c -o main.o
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c -mthumb main.c -o main.o
arm-none-eabi-ld -Ttext=0x08000000 start.o main.o -o main.elf
arm-none-eabi-objdump -d main.elf
main.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000 .word 0x20001000
8000004: 08000008 .word 0x08000008
08000008 <reset>:
8000008: f000 f802 bl 8000010 <xmain>
800000c: e7fe b.n 800000c <reset+0x4>
...
08000010 <notmain>:
8000010: 2000 movs r0, #0
8000012: 4770 bx lr
I tried looking through the toolchain in my files to find any other reference to main pertaining to linker scripts and got some other help along the way, but there doesnt seem to be a clear solution as to why this is. Of course, if you create your own linker or a generated one you wont run into this problem, but I was just curious as I am trying to learn the tool a bit more.
..but I was just curious as I am trying to learn the tool a bit more
The arm-eabi-none is meant to be used with newlib (as a guess because you have not stated otherwise). This can process elf format files and it is a 'library', but there is no OS. If newlib mechanics want main() to be first, the tool will set things up like this. You don't want an elf file, but a binary. If you want a binary (ihex, srec, etc), then use a linker script! This is what it is meant for.
Use ld --verbose to see the default linker script. You are complaining about the order of emitted .text, but you have done nothing to define the ordering. The linker script may need main to be first so that some other library feature may work. You have a reset vector and a CPU which initializes the stack and 'reset vector' or initial code.
This is still emitted in the 'bad case', but it is not placed correctly. You need to have a custom linker script and position this a the first thing in the binary. Relying on the linker to place it correctly is error prone. An upgrade of tools can definitely change the order.
See: Can _start be a thumb function, were you have options like, -nostartfiles -static -nostdlib and use a custom linker script as an elf binary is unlikely to be understood and you need to flash/burn a binary to whatever boot device (or CPU built-in) is going to read the reset vectors.

MinGW Win32 + nasm: "undefined reference"

I am currently developing an OS for learning purposes, and it's been working fine until now. Then I tried to call an assembler function, compiled with nasm, -fwin32, from C code, but all I got was an "undefined reference" error. I have created a small example in pure assembler, which has the same problem, but is easily understandable and way smaller:
It includes two files:
test.asm:
[bits 32]
global _testfunc
_testfunc:
ret
test2.asm:
[bits 32]
extern _testfunc
global _testfunc2
_testfunc2:
call _testfunc
ret
Here is my compiler / linker script (using windows batch files):
nasm.exe -f win32 test.asm -o test.o
nasm.exe -f win32 test2.asm -o test2.o
ld test.o test2.o -o output.tmp
This results in the error:
test2.o:test2.asm:(.text+0x1): undefined reference to `testfunc'
To extend the question, the same happens when the function is called from C:
test.c:
extern void testfunc(void);
void start()
{
testfunc();
}
With this linker script:
gcc -ffreestanding -c test.c -o testc.o
nasm.exe -f win32 test.asm -o test.o
ld test.o testc.o -o output.tmp
In test.o, test2.o and testc.o, it always says _testfunc, so the error has nothing to do with leading underscores!
In my MinGW setup you need a section directive before the code.
; foo.asm
[bits 32]
global _testfunc
section .text
_testfunc:
ret
Then assemble to win32 format:
nasm -fwin32 foo.asm -o foo.o
Now you can check that testfunc is there:
$ nm foo.o
00000000 a .absolut
00000000 t .text
00000001 a #feat.00
00000000 T _testfunc
The T means text section global, so we're good to go.
Note I'd avoid naming anything test since this is a shell command. This can cause endless grief.
The C function is as you showed it, but name the file something else:
// main.c
extern void testfunc(void);
int main(void)
{
testfunc();
return 0;
}
Then to build an executable let gcc do the heavy lifting because ld sometimes needs arcane arguments.
gcc -ffreestanding main.c foo.o -o main
Your missing something important, your code is not in a code section!
Your asm files should look like the following:
test.asm
global _testfunc
section .text ; <<<< This is important!!!
; all code goes below this!
_testfunc:
ret
test2.asm
extern _testfunc
global _testfunc2
section .text ; <<<< Again, this is important!!!
_testfunc2:
call _testfunc
ret

Nasm on Mac OS X - how to compile and read the debug

I'm trying to learn assembly and I'm using Nasm v2.10.07 on Mac OS X (Snow Leopard).
I can compile, but I need to read the Debug file, that is a .o file.
This is what I compile:
global _main
section.data
M db 5,4,3,2,1
dim equ $-M
section.text
_main:
mov edi, M
mov eax, 0
mov ebx, 1
int 80h
This is how I compile:
nasm -f elf -g -F stabs myfile.asm -o myfile.o
And this is the result:
ELF����������������������#�������4�����(�
�������������������������������������������������������������������–������������������������������������?��������������������������������0��M��������������������������������Ä��ê���������������"����������������2������������������*��� �����������P�����������������4��������������`��T����������������:��������������¿��������������������C��� �����������–��0���������������ø����∏����ª���ÕÄ�%define $�The Netwide Assembler 0.98.40 (Apple Computer, Inc. build 11)���.text�.comment�.shstrtab�.symtab�.strtab�.rel.text�.stab�.stabstr�.rel.stab��%d����������������������������Òˇ�������������Òˇ������������������������������������������������������Òˇ�������������,�������������myfile.asm�section.data�M�dim�section.text�_main��%define $_%1 ������%define������������d�����������D����������D���������D��
�������D� ��������D�
�����%define $_%�myfile.asm��%de����� �����,�����8�����D�����P�����
So, what should I do to read in the correct way the debug without those strange symbols?
To show the contents of the .stabs section, use objdump -g myfile.o or objdump -G myfile.o
To get the full source code with line numbers taken from the debug section, use objdump -S -l myfile.o

NASM Hello World either segfaults or bus errors in Mac OS X

I'm writing Hello World in NASM, and I can get it to echo Hello World to the console, but the program segfaults if I don't run it with Make.
Trace with Makefile:
$ make
nasm -f macho -o hello.o --prefix _ hello.asm
ld -o hello hello.o -arch i386 -lc -macosx_version_min 10.6 -e _start -no_pie
./hello
Hello World!
Trace with manual commands:
$ nasm -f macho -o hello.o --prefix _ hello.asm
$ ld -o hello hello.o -arch i386 -lc -macosx_version_min 10.6 -e _start -no_pie
$ ./hello
Segmentation fault: 11
hello.asm:
[bits 32]
section .data
msg: db "Hello World!", 0
section .text
global start
extern puts
extern exit
start:
push msg
call puts
add esp, 4
push 0
call exit
Makefile:
# Linux defaults
FORMAT=-f elf
MINV=
ARCH=-arch i386
LIBS=
RUN=./
EXECUTABLE=hello
PREFIX=
ENTRY=
PIE=
# Windows
ifeq (${MSYSTEM},MINGW32)
FORMAT=-f win32
EXECUTABLE=hello.exe
PREFIX=--prefix _
ENTRY=-e _start
ARCH=
LIBS=c:/strawberry/c/i686-w64-mingw32/lib/crt2.o -Lc:/strawberry/c/i686-w64-mingw32/lib -lmingw32 -lmingwex -lmsvcrt -lkernel32
ENTRY=
RUN=
endif
# Mac OS X
ifeq ($(shell uname -s),Darwin)
FORMAT=-f macho
PREFIX=--prefix _
ENTRY=-e _start
LIBS=-lc
MINV=-macosx_version_min 10.6
PIE=-no_pie
endif
all: test
test: $(EXECUTABLE)
$(RUN)$(EXECUTABLE)
$(EXECUTABLE): hello.o
ld -o $(EXECUTABLE) hello.o $(ARCH) $(LIBS) $(MINV) $(ENTRY) $(PIE)
hello.o: hello.asm
nasm $(FORMAT) -o hello.o $(PREFIX) hello.asm
clean:
-rm $(EXECUTABLE)
-rm hello.o
Specs:
ld 64-134.9
LLVM 3.1svn
NASM 0.98.40
Make 3.81
Xcode 4.5
Mac OS X 10.8.1
MacBook Pro 2009
2 things, your hello world string is not NULL terminated and as I mentioned in another post, when you use C functions, you MUST adjust esp after each call
You tore down your stack frame twice:
mov esp, ebp
pop ebp
...
leave
You only need one of those, since leave is equivalent to mov esp, ebp; pop ebp.
See http://michaux.ca/articles/assembly-hello-world-for-os-x for several example hello world programs. Note that all of them exit the program explicitly with
; 2a prepare the argument for the sys call to exit
push dword 0 ; exit status returned to the operating system
; 2b make the call to sys call to exit
mov eax, 0x1 ; system call number for exit
sub esp, 4 ; OS X (and BSD) system calls needs "extra space" on stack
int 0x80 ; make the system call
because you cannot ret from an entry point (there's nothing to return to).
Also note that if you call the function main and don't supply the e option to ld, then libc's entry point will be called. In that case, it is permissible to ret since you will return control to libc (which calls exit on your behalf).

Resources