1

I am writing a hello world program for linux x86_64 using GAS assembler and here is my code in AT&T syntax.

#.intel_syntax noprefix

.section .data
    msg:
        .ascii "hello world\n"
.section .text
.globl _start
_start:
    movq  $1, %rax
    movq  $1, %rdi
    movq  $msg, %rsi
    movq  $12, %rdx
    syscall

    movq  $60, %rax
    movq  $0, %rdi
    syscall

This works and prints "hello world". Here is intel syntax:

.intel_syntax noprefix

.section .data
    msg:
        .ascii "hello world\n"
.section .text
.globl _start
_start:
    mov rax, 1
    mov rdi, 1
    mov rsi, msg
    mov rdx, 12
    syscall

    mov rax, 60
    mov rdi, 0
    syscall

This compiles and runs fine but does not print "hello world". I am assuming the mistake is in mov rsi, msg? If so, what is the correct syntax?

wingerse
  • 3,670
  • 1
  • 29
  • 61

2 Answers2

7

Try mov rsi, offset msg. gas uses a masm-like syntax where mov rsi, msg moves the content of msg to rsi instead of moving the address. The offset keyword has to be used to avoid this issue.

If you want to program in Intel syntax, I advise you to pick a better assembler like nasm.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • 1
    @WingerSendon Note that you need go back to your original code and fix some of the directives for it to assemble on nasm, but the syntax is overall much saner than with gcc in Intel syntax. – fuz Jul 26 '18 at 16:56
3

You can use an AT&T syntax disassembler (like objdump -d) to see that mov rsi, msg in GAS .intel_syntax assembles to mov msg, %rsi, a 64-bit load from a 32-bit-absolute address.

Or use objdump -d -Mintel to see Intel-syntax disassembly for your working version.

GDB has set disassembly-flavor intel or att, so you can flip even within one debugging session.


And BTW, you should use RIP-relative LEA to get 64-bit static addresses into registers. It's more efficient than mov r64, imm64

lea   msg(%rip), %rsi    # AT&T

lea   rsi, [msg + rip]  # GAS .intel_syntax

lea   rsi, [rel msg]     ; NASM

(but less efficient than mov r32, imm32 in a position-dependent executable where static labels are in the low 31 bits of virtual address space.)

 ## In x86-64 position-dependent executables on Linux

 mov  $msg, %esi            # AT&T

 mov   esi, OFFSET msg      # GAS .intel_syntax

 mov   esi, msg          ; NASM

Note that OS X puts static addresses outside the low 32, so you even in an executable your addresses are 64-bit. Unable to move variables in .data to registers with Mac x86 Assembly

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847