6

The GNU assembler gives an unexpected memory operand when assembling Intel syntax code.

I have reduced my bug to one single lonely line of code, and for the last three days I've tried anything to understand why the GNU assembler yields something that I cannot understand. I know this must (or should) be trivial, but I'm at a loss.

The following text resided in the file code.asm:

.intel_syntax noprefix
.global somecode
somecode: 
    int 3
    mov        rax,qword [rcx]
    ret
.att_syntax

Assembling and disassembling code.asm with:

as code.asm -o code1.obj -64 
objdump -Mintel -d code1.obj > code1.asm

The content of code1.asm (with the disassembled code) is:

code1.obj:     file format pe-x86-64
Disassembly of section .text:
0000000000000000 <somecode>:
   0:   cc                      int3 
   1:   48 8b 41 08             mov    rax,QWORD PTR [rcx+0x8]
   5:   c3                      ret    

I'm using GNU assembler (GNU Binutils) 2.25 (`x86_64-pc-cygwin').

Question: Why is there an extra one qword offset (8bytes) in the memory operand QWORD PTR [rcx+0x8]? I expect mov rax,QWORD PTR [rcx].

I must be doing something wrong. So I cross-checked with another respected assembler Yasm and ran:

yasm -f x64 -o code2.obj --parser=gas code.asm
objdump -Mintel -d code2.obj > code2.asm

The content of code2.asm is:

code2.obj:     file format pe-x86-64
Disassembly of section .text:
0000000000000000 <somecode>:
   0:   cd 03                   int    0x3
   2:   48 8b 01                mov    rax,QWORD PTR [rcx]
   5:   c3                      ret

With regard to the memory operand, this is what I expected. How can I instruct GNU to do the same?

HJLebbink
  • 719
  • 1
  • 11
  • 32
  • 2
    `qword` instead of `qword ptr` is NASM syntax. GAS unfortunately doesn't error on it, and has this "failure mode" because it allows `123[reg]` as address syntax. I think there are also some SO Q&As about MASM itself having plain `dword` be the constant `4`, which also seems terrible. Especially for MASM, it has keywords like `typeof` to turn a typename into a size for `add edi, typeof foo`. Poor design IMO. – Peter Cordes Jun 30 '21 at 17:42

1 Answers1

5

You need to write mov rax, qword ptr [rcx]. Apparently qword by itself resolves to the size, ie. 8, so your code assembled as mov rax, 8[rcx]. Indeed, mov rax, qword also assembles as mov rax, 8.

It's funny how your "cross check" used the proper syntax :)

Jester
  • 56,577
  • 4
  • 81
  • 125
  • 1
    Brilliantly simple, this makes sense and it works, thanx. This is a real bug magnet. There ought to have been some warning... – HJLebbink May 07 '15 at 20:50