How do I compile assembly? - macos

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.

Related

what are the correct flags to mix assembly and C without losing .data constants

I am working on a utility in assembler (x86, NASM 2.13, gcc 7.50, Ubuntu 18.X) to be called from C. The problem that I am running into is that the string constant addresses seem to be lost in the making process, so messages are not printing. I can see the string constants in the final binary.
This is the sample assembler code
SECTION .data
error_len_message: db "test", 10
error_len_message_len: equ $-error_len_message
SECTION .text
global test_func
test_func:
mov eax, 4
mov ebx, 1
mov ecx, error_len_message
mov edx, error_len_message_len
int 80H
The header file would be trivial as it would only need the signature used in main.c
#include "....."
int main(void) {
test_func();
return 0;
}
The make file of the executable is as follows:
util_tests: ../asm/utilities/utilities.o
gcc -Wall -o ./build/$# main.c $?
../asm/utilities/utilities.o:
cd ../asm/utilities && make && cd ../../util_tests;
clean:
cd ../asm/utilities && make clean && cd ../../util_tests;
The make file of the utilities is as follows:
utilities.o: test/test.o
ld $? -o $#
test/test.o:
cd test && make && cd ..;
clean:
cd test && make clean && cd ..;
rm *.o
The make file of test assembler code is:
test.o: test.asm
nasm -f elf64 -g -F dwarf $?
clean:
rm *.o
I have no trouble turning this into an executable using assembler only and printing strings defined in .data section. Make file:
test: test.o
ld -o test $^
test.o: *.asm
nasm -f elf64 -g -F stabs $?
clean:
rm *.o
I can successfully define and use variables in the .bss section (not shown for brevity)
The problem, I believe, is in the way I am building the utility. Thanks in advance!
So after adding the pertinent "default rel" to the assembler source file, removing direct calls to int 80H, and adding calls printf, the linker fails because it also tries to relocate "printf#glibc_x.x.x". After trying linker options to ignore unresolved symbols, it seems like a dead end.
So it seems there are only two choices, assemble in 32 bit to avoid problems with "int 80H", or return status/results and let the caller deal with the rest. The following assemble, link, and gdb displays labels and offsets matching correctly
DEFAULT REL
SECTION .text
global silly
silly:
lea r9, [message]
ret
SECTION .data
message: db "A Message", 10
Makefile:
silly.so: silly.o
ld -shared $? -o $#
silly.o: silly.asm
nasm -f elf64 -g -F dwarf $?
clean:
rm *.o
rm *.so
Hopefully, this would be useful to anyone

Segmentation fault call printf NASM

I'm using a Macbook pro with Yosemite. Can't get the printf to work. Here's my code:
extern _printf
global _main
section .data
msg: db "Hello World"
section .text
_main:
push msg
call _printf
add esp, 4
ret
Using:
nasm -f macho test.s && gcc -arch i386 -e _main test.o && ./a.out
Output:
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in _main from test.o. To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
Segmentation fault: 11
I'd really appreciate any help.
This answered my question perfectly! How to print argv[0] in NASM?

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 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).

link nasm program for mac os x

i have some problems with linking nasm program for macos:
GLOBAL _start
SEGMENT .text
_start:
mov ax, 5
mov bx, ax
mov [a], ebx
SEGMENT .data
a DW 0
t2 DW 0
fry$ nasm -f elf test.asm
fry$ ld -o test test.o -arch i386
ld: warning: in test.o, file was built for unsupported file format which is not the architecture being linked (i386)
ld: could not find entry point "start" (perhaps missing crt1.
fry$ nasm -f macho test.asm
fry$ ld -o test test.o -arch i386
ld: could not find entry point "start" (perhaps missing crt1.o)
can anyone help me?
The Mac OS X linker can't link ELF objects. It works only with the Mach-O executable format. Unless you want to figure out how to translate the object files, you'll probably be better off writing code that works with the Mac OS X assembler.
Edit: As #Fry mentions in the comment below, you can make nasm put out Mach-O objects. In that case, the problem is simple - take the _ off of _start in both places in your source file. The result links fine.
nasm -f macho test.asm
ld -e _start -o test test.o
For people who need to stick with the elf format and develop on a mac, you need a cross compiler...
http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux
Then you can proceed with something similar to this...
/usr/local/gcc-4.8.1-for-linux32/bin/i586-pc-linux-ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o

Resources