I'm on a Linux x86_64 system and my goal is to create an assembly program inside the classic main function. I've tried this and it works fine :
.code64
.section .rodata
msg: .ascii "Hello, World!\n"
.set msglen, (. - msg)
.section .text
.global _start
_start:
mov $1, %rax
mov $1, %rdi
lea msg, %rsi
mov $msglen, %rdx
syscall
mov $60, %rax
mov $0, %rdi
syscall
I compiled this with "as -o hello.o -s hello.s" and then linked with "ld -o hello hello.o"
However I want my program to be inside the main function and be compiled and linked with respectively "as main.s (... options ) -o main.o" and "gcc main.o (...options) -o main". How can I do that ?
Change
_starttomain, and uselea msg(%rip), %rsiso your code isn't using any 32-bit absolute addresses (and is position-independent)How to load address of function or label into register
32-bit absolute addresses no longer allowed in x86-64 Linux?
You can also replace the exit system-call with a
ret. Since you didn't need to make any library function calls or move the stack pointer for any other reason, it's still pointing at the return address.You should also remove
.code64. That's already the default state when assembling into a 64-bit ELF object file. The only time it makes a difference is withgcc -m32(as --32) when you'd rather have the assembler tell you that RAX isn't a register instead of assembling 64-bit machine code into a 32-bit object file to eventually get decoded differently when the CPU runs it in 32-bit mode. Only use mode overrides like.code32or.code64when you're mixing bitness within the same program, such as for a kernel, or doing weird hacky stuff like a far-jump (AT&Tljmp) to a different mode in user-space.If you're using
gcc, you don't need to assemble separately, you can have it run the assembler for you likegcc -c main.Sand then link, or justgcc main.Sto assemble + link, exactly like howgcc hello.cwill compile + assemble + link.