How do I go about creating a GAS AT&T format main assembly program that uses the syscall instruction to print "Hello World"?

55 views Asked by At

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 ?

1

There are 1 answers

5
Peter Cordes On

Change _start to main, and use lea msg(%rip), %rsi so your code isn't using any 32-bit absolute addresses (and is position-independent)


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 with gcc -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 .code32 or .code64 when you're mixing bitness within the same program, such as for a kernel, or doing weird hacky stuff like a far-jump (AT&T ljmp) 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 like gcc -c main.S and then link, or just gcc main.S to assemble + link, exactly like how gcc hello.c will compile + assemble + link.