32

I just found a strange instruction by assembling (with gas) and disassembling (with objdump) on a amd64 architecture.

The original amd64 assembly code is:

mov 0x89abcdef, %al

And, after gas compiled it (I am using the following command line: gcc -m64 -march=i686 -c -o myobjectfile myassemblycode.s), objdump gives the following code:

a0 df ce ab 89 00 00    movabs 0x89abcdef, %al

My problem is that I cannot find any movabs, nor movab in the Intel assembly manual (not even a mova instruction).

So, I am dreaming ? What is the meaning of this instruction ? My guess is that it is a quirks from the GNU binutils, but I am not sure of it.

PS: I checked precisely the spelling of this instruction, so it is NOT a movaps instruction for sure.

3

5 Answers 5

29

Here's the official documentation for gas, quoting the relevant section:

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.

Particularly read the last sentence.

Note: Found via Google operator inurl, searching for movabs inurl:sourceware.org/binutils/.

4
  • I looked at the gas manual but I did not find the right section. Thanks a lot 0xC0000022L ! :-)
    – perror
    Aug 12, 2013 at 19:53
  • How can you move a 32 bit number into al?
    – phuclv
    Sep 25, 2013 at 6:24
  • @LưuVĩnhPhúc: well you can only with losses, but this has nothing to do with my answer or the question, so you better ask it as a new question.
    – 0xC0000022L
    Sep 25, 2013 at 7:17
  • What's interesting, gdb gives me 48 b8 <imm64> bytes as movabs rax, <imm64> even in disassembly-flavor=intel.
    – Ruslan
    Oct 30, 2014 at 10:31
9

movabs is used for absolute data moves, to either load an arbitrary 64-bit constant into a register or to load data in a register from a 64-bit address.

Source: http://www.ucw.cz/~hubicka/papers/amd64/node1.html

8

If you find yourself often deciphering AT&T syntax x86/x64 assembler, Solaris manuals may be of help: x86 Assembly Language Reference Manual .

1
  • 1
    good downloadable reference thanks igorsk for the link
    – blabb
    Aug 13, 2013 at 9:00
3

I noticed that GAS translates

movq $0x80000000, %rax

into

movabs 0x80000000, %rax

But values smaller than 0x80000000 movement is not translated into movabs. That is, movq $0x7fffffff, $rbx is NOT translated into movabs $0x7fffffff, %rbx. You can verify with disas disassemble command within GDB.

Maybe the reason is that $0x80000000 is over the signed positive number range of 32 bit and needs to be translated into 64-bit integer. For the reason, GAS translates such larger number into 64-bit long integer and therefore uses movabsq instruction instead of movq instruction whose immediate source is limited to 32 bit constant.

1
  • this is incorrect movq $0x80000000, %rax moves the immediate 0x80000000 into rax whereas movabs 0x80000000, %rax loads the quadword at address 0x80000000 to rax
    – phuclv
    Aug 8, 2018 at 6:30
1

Initialization of local variables with movabs

Yes this instruction should move absolute hardcoded data embedded into instruction itself into register, or data from absolute address. But I got into this instruction only recently when I wanted to know where constant data for initialization of local variables are because I didnt find them in .rodata ELF section.

So basically GCC uses this instruction to initialize automatic variables on stack!

Lets dive into code to find out how this instruction is used. As we see in this code example we have local variable test initialized:

enter image description here

We know that local variables are put in stack and I was interested to know where and how local variables get initialized.

When we dump .text section with objdump we see that this constant 0x41414141414141 is realy embedded in the code itself:

000000000000116c <get_message2>:
116c:   f3 0f 1e fa             endbr64 
1170:   55                      push   %rbp
1171:   48 89 e5                mov    %rsp,%rbp
1174:   48 83 ec 10             sub    $0x10,%rsp
1178:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
117f:   00 00 
1181:   48 89 45 f8             mov    %rax,-0x8(%rbp)
1185:   31 c0                   xor    %eax,%eax
1187:   48 b8 41 41 41 41 41    movabs $0x41414141414141,%rax
118e:   41 41 00 

As we see disassembled function and register content from GDB:

enter image description here

So when we look at code we see that this string test, in HEX notation 0x0x41414141414141 is hardcoded in movabs instruction, and is put in rax register, and then content of rax register is put on address in rbp minus offset 0x10:

   0x000055555555517d <+27>:    movabs $0x41414141414141,%rax
   0x0000555555555187 <+37>:    mov    %rax,-0x10(%rbp)

So this local string will be placed on address 0x7fffffffdde0 - 0x10 We see that this local string is placed in stack frame of function on address 0x7fffffffddd0, and this we see when we dump the stack:

(gdb) x/16gx $sp
0x7fffffffddd0: 0x0041414141414141  0x6a8574f1d6812b00
0x7fffffffdde0: 0x00007fffffffddf0  0x000055555555515b
0x7fffffffddf0: 0x0000000000000001  0x00007ffff7daad90 

So we ended with initialized local string on a stack just as we expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.