-2

I just compiled a CPP source code into an object .o file, and the first couple of lines are like the following:

Disassembly of section .text:

0000000000000000 <_Z8mainLoopv>:
   0:   f3 0f 1e fa             endbr64 
   4:   55                      push   %rbp
   5:   48 89 e5                mov    %rsp,%rbp
   8:   41 55                   push   %r13
   a:   41 54                   push   %r12
   c:   53                      push   %rbx
   d:   48 81 ec 88 00 00 00    sub    $0x88,%rsp
  14:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax

I am assuming the first column is the adress of the instructions, am I right? If so, why aren't they consecutive? Something like this:

   0:   f3 0f 1e fa             endbr64 
   1:   55                      push   %rbp
   2:   48 89 e5                mov    %rsp,%rbp
   3:   41 55                   push   %r13
   4:   41 54                   push   %r12
   5:   53                      push   %rbx
   6:   48 81 ec 88 00 00 00    sub    $0x88,%rsp
   7:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
E_net4
  • 27,810
  • 13
  • 101
  • 139
Joao Donasolo
  • 359
  • 1
  • 9
  • 10
    Some instructions occupy several bytes. Notice the different row lengths. – HolyBlackCat Jan 16 '22 at 17:18
  • 1
    @HolyBlackCat Simpler than I thought haha thanks – Joao Donasolo Jan 16 '22 at 17:22
  • 2
    Note that data is similar: mulit byte data is referred to by lowest address among its bytes; consecutive mulit byte elements in an array will appear to skip addreses, for example. – Erik Eidt Jan 16 '22 at 18:30
  • they are sequential. start at 0 then each byte in that instruction is 1,2,3, then 4 is next, then 5,6,7, then 8 and so on. – old_timer Jan 16 '22 at 22:56
  • 2
    *Ps.: Why you guys downvoting this?* - I didn't downvote, but I assume the downvotes are from people who thought the answer was completely obvious given a basic understanding of bytes and addresses. It was probably even obvious to you once you read the answer, but that doesn't necessarily make it a bad SO question. You did format it well, and clearly explain exactly what you're wondering about so it was possible to answer it easily, without a lot of guesswork to figure out what misconception it was based on. If this ever comes up again, now we have a canonical Q&A for it. – Peter Cordes Jan 17 '22 at 16:36

2 Answers2

3

Each instruction can take more than one bytes of space. Here, the first instruction takes four bytes of space(f3 0f 1e fa) so the next instruction starts at byte 4.

Shahriar
  • 768
  • 4
  • 11
3

The first column is the address of the instruction.

Because x86_64 instructions aren't the same length (like ARM64 for example), the value difference varies. The second column show the bytes of each instructions. Notice that they have different lengths.

ntrung03
  • 147
  • 2
  • 8
  • 1
    Yes, but the addresses in a `.o` are calculated starting at 0 for the first instruction in the *file*, not the function. Linkers don't really know about functions, just symbol addresses and relocation entries. (i.e. the infrastructure needed to compile high-level code with functions into linkable object files). In a linked executable, addresses would start from some base address. (In a PIE, probably `0x1000`, or for a non-PIE often `0x401000` on Linux, IIRC.) – Peter Cordes Jan 16 '22 at 17:40
  • 2
    Note that ARM64 is not a fixed-length instruction set either as SVE instructions come with prefixes. – fuz Jan 16 '22 at 18:15
  • @PeterCordes Ahh yeah, my bad. I was trying to make a offset base out of the blue to explain... – ntrung03 Jan 16 '22 at 22:48
  • @fuz What? I've never seen an ARM64 instruction that is longer than 4 bytes. I'm talking about ARMv8 64bit – ntrung03 Jan 16 '22 at 22:49
  • @ntrung03 Basically, with SVE there are prefix instructions that modify the following instruction. These can be implemented as separate instructions, but they are meant to be decoded and implemented as 8 byte long instructions. It's similar to how `IT` behaves as a prefix in Thumb mode when only one instruction is affected. ARM has deprecated most other uses of `IT` so it can be thought of as a prefix in a variable length instruction set. – fuz Jan 16 '22 at 23:29
  • @ntrung03: You can [edit] your answer to correct that minor point. That's what comments are for. – Peter Cordes Jan 17 '22 at 01:28
  • @fuz, section A1.3.2 of the ARMv8 ARM (DDI 0487G.a) states that `AArch64 state supports only a single instruction set, called A64. This is a fixed-length instruction set that uses 32-bit instruction encodings.` – ntrung03 Jan 17 '22 at 06:05
  • @fuz Do you have a source for that? Or even just an example of such "prefixes"? Your claim seems to contradict everything the ARMv8 Reference Manual has to say about this. – Siguza Jan 17 '22 at 10:21
  • @Siguza See the [`MOVPRFX` instruction](https://developer.arm.com/documentation/ddi0596/2021-06/SVE-Instructions/MOVPRFX--unpredicated---Move-prefix--unpredicated--). The SVE section in the ARM Architecture Reference Manual provides further details on how it behaves like a prefix. – fuz Jan 17 '22 at 10:56
  • @Siguza: It may be a sort of semantic argument. I guess the idea is that you do `MOVPRFX z0, z1 ; SDIV z0, z2` to get the effect of `SDIV z0, z1, z2`. You could think of the two as a single 8-byte instruction. Or you could think of `MOVPRFX` as an independent instruction which simply has the effect of `MOV z0, z1`, but with the additional requirement that the following instruction must be one of a certain set, and with the "hint" that the machine may be able to fuse the two. – Nate Eldredge Jan 17 '22 at 17:04
  • @Siguza: So if you still want to think that every instruction is 4 bytes, you just have to resign yourself to the possibility that some instructions' behavior depends on which instruction follows them in sequence (here, the behavior of `MOVPRFX` may be either `MOV` or `UNPREDICTABLE`). – Nate Eldredge Jan 17 '22 at 17:06
  • I was wondering why they would introduce this, instead of just encouraging core designers to make MOV execute in zero cycles at register renaming, as some machines can do. Then programmers could just write `MOV z0, z1 ; SDIV z0, z2` as usual, and be eligible for the same performance gain. But it seems that zero-cycle move is [patented by Apple](https://patents.google.com/patent/US20130275720A1/), so maybe this was an attempt to design around that patent? Juts a guess. – Nate Eldredge Jan 17 '22 at 17:17