How to copy the value at a certain address in memory to a register in gcc AT&T style

15,940

To copy the value at a certain address in memory to a register in 32-bit mode we use

mov edi, [0xdeadbeef] ; Intel
movl 0xdeadbeef, %edi ; AT&T

In AT&T any literal that is not prefixed by $ is an address

But in x86_64 64-bit absolute addressing is not allowed, so you can't use movq 0xdeadbeef, %rdi like above. The only instruction that has 64-bit immediate is mov (movabs in gas), which can assign a 64-bit constant to any registers, or move value at a 64-bit absolute address to Areg

mov rax, [0xdeadbeef]   ; Intel
movabs 0xdeadbeef, %rax ; AT&T

If you really need to move the value from a 64-bit absolute address to a register different from Areg you must use indirect addressing instead

mov rdi, 0xdeadbeef     ; Intel
mov rdi, [rdi]

movq $0xdeadbeef, %rdi  ; AT&T
movq (%rdi), %rdi

or if you want the value to be copied to both rax and rdi then

mov rax, [0xdeadbeef]   ; Intel
mov rdi, rax

movabs 0xdeadbeef, %rax ; AT&T
movq %rax, %rdi

Here the q suffix means quadword (64-bit) registers

In AT&T syntax the size of memory operands is determined from the last character of the instruction mnemonic. Mnemonic suffixes of b, w, l and q specify byte (8-bit), word (16-bit), long (32-bit) and quadruple word (64-bit) memory references. Intel syntax accomplishes this by prefixing memory operands (not the instruction mnemonics) with byte ptr, word ptr, dword ptr and qword ptr. Thus, Intel mov al, byte ptr foo is movb foo, %al in AT&T syntax.

In 64-bit code, movabs can be used to encode the mov instruction with the 64-bit displacement or immediate operand.

https://sourceware.org/binutils/docs/as/i386_002dVariations.html

More information about 64-bit mov instruction here: Difference between movq and movabsq in x86-64. As you can see there's no version for moving from a 32-bit absolute address to a 64-bit register, so even in rare cases when the address fits in 32 bits like 0xdeadbeef, you still have to use movabs Areg, moffs64

Share:
15,940
Gnijuohz
Author by

Gnijuohz

I use Python primarily nowadays. I've previously worked with Django on several small projects and now trying out Flask. I have some experience with front end web development as well. Been using Mongodb for the past few months and am quite happy with it so far. I also developed an iOS app with Swift and node.js named GeeksforGeeks Reader, which has good reviews in the U.S. App Store. I'm interested in working with Swift, node.js more in the future.

Updated on June 04, 2022

Comments

  • Gnijuohz
    Gnijuohz almost 2 years

    I want to copy the value at a certain address in memory to a register using AT&T style assembly. I know this shouldn't be hard, and I think in Intel style it's something like:

    mov rdi, [0xdeadbeef]
    

    But I don't know much about the AT&T style (or assembly in general). I searched about it but all the examples about mov that I got didn't include this one.

    So can anyone tell me how that instruction looks like?

    Also, where can I find a complete list of x86_64 assembly instructions in AT&T style?

  • Gnijuohz
    Gnijuohz over 10 years
    Should it be mov 0xdeadbeef, %rdi? Because in AT&T the destination should be the second one. So $0xdeadbeef copies the value and 0xdeadbeef copies the address?
  • phuclv
    phuclv over 10 years
    no, Intel style mov [0xdeadbeef], rdi would be reversed in AT&T syntax, which is like the one I wrote above
  • Gnijuohz
    Gnijuohz over 10 years
    ok, my intel style instruction was wrong... Based on what I asked for, which is 'move value from memory to register' it should be the way I commented.
  • phuclv
    phuclv over 10 years
    Ahhh, your Intel style example is wrong. To copy the value from an address to a register the instruction should be mov rdi, [0xdeadbeef], which is movq 0xdeadbeef, %rdi in AT&T
  • Gnijuohz
    Gnijuohz over 10 years
    Now I'm confused... Could you explain the following three instructions? 1. mov $5, %rdi 2. mov $0xdeadbeef, %rdi 3. mov 0xdeadbeef, %rdi.The first one is moving the value 5 to rdi, the second one and the third one which is moving the value at the address, which one is moving the address 0xdeadbeef??? I thought the second one was moving the value because of the $ sign...
  • phuclv
    phuclv over 10 years
    I've said that any number that is not prefixed by $ is and address. So the first 2 instructions will move the value (5 and 0xdeadbeef) to rdi. Only the last one move data from the address 0xdeadbeef to rdi. Look at the answer here
  • Gnijuohz
    Gnijuohz over 10 years
    I see! Thanks so much for the clarification!
  • Gnijuohz
    Gnijuohz over 10 years
    Sorry but actually your answer gives an error suffix or operands invalid for 'mov' so I have to unchoose it as the answer...
  • phuclv
    phuclv over 10 years
    That's because you're compiling in the wrong mode. You must specify "-m64" or "-mx32" to use 64-bit registers and "q" suffix. Look at Differences between NASM, MASM, and GAS here, it also states that to move contents of address 10 into register ecx, use mov ecx, [10] or movl 10, %ecx
  • phuclv
    phuclv over 10 years
    I understand why. 32-bit absolute address is not supported on x86_64. Edited my answer
  • Peter Cordes
    Peter Cordes almost 6 years
    I think you read the question title backwards. It is asking for mem -> reg, like its Intel-syntax instruction is doing.
  • phuclv
    phuclv almost 6 years
    @PeterCordes originally the OP had written mov [0xdeadbeef], rdi which was reg -> mem
  • Peter Cordes
    Peter Cordes almost 6 years
    Ok, but your AT&T syntax mov %rdi, 0xdeadbeef is a store.
  • phuclv
    phuclv almost 6 years
    @PeterCordes that was the answer to the old question. I've updated to make it clearer
  • Peter Cordes
    Peter Cordes almost 6 years
    The title was always mem to reg. Preserving that historical detail as the very first thing in your current answer to the fixed question really brings it down, IMO. At least move it to a PS section or something.
  • Peter Cordes
    Peter Cordes about 2 years
    BTW, 32-bit absolute addressing is allowed for any instruction: NASM a32 mov rdi, [abs 0xdeadbeef] is encodeable because the address-size prefix truncates to 32-bit with zero-extension back to 64, unlike normal ModRM [abs disp32] encoding which sign-extends. That's the problem here with 0xdeadbeef, which is outside the low 2G but still in the low 4G. Objdump disassembly is 67 48 8b 3c 25 ef be ad de mov 0xdeadbeef(,%eiz,1),%rdi (because 32-bit absolute uses a SIB with no index I guess)
  • Peter Cordes
    Peter Cordes about 2 years
    In AT&T syntax, addr32 mov 0xdeadbeef, %rdi.
  • Peter Cordes
    Peter Cordes about 2 years
    mov rax, [0xdeadbeef] isn't correct NASM syntax for movabs. Unfortunately you need mov rax, [qword 0xdeadbeef], otherwise it just warns about dword data exceeds bounds and encodes a disp32 load from 0xffffffffdeadbeef