Search code examples
assemblyx86-64attaddressing-mode

What does a minus before an addressing mode mean in assembly, like -0x2(%rbx)


                    201036:    push   %rbp
                    201037:    push   %rbx
                    201038:    sub    $0x28,%rsp
                    20103c:    mov    %rsp,%rsi
                    20103f:    callq  2014a5 <read_input>
                    201044:    cmpl   $0x0,(%rsp)
                    201048:    jne    201051 <func_2+0x1b>
                    20104a:    cmpl   $0x1,0x4(%rsp)
                    20104f:    je     201056 <func_2+0x20>
                    201051:    callq  20146f <wrong_input>
                    201056:    mov    %rsp,%rbp
                    201059:    lea    0x4(%rsp),%rbx
                    20105e:    add    $0x18,%rbp
                    201062:    mov    -0x2(%rbx),%eax
                    201065:    add    -0x4(%rbx),%eax
                    201068:    cmp    %eax,(%rbx)
                    20106a:    je     201071 <func_2+0x3b>
                    20106c:    callq  20146f <wrong_input>
                    201071:    add    $0x2,%rbx
                    201075:    cmp    %rbp,%rbx
                    201078:    jne    201062 <func_2+0x2c>
                    20107a:    add    $0x28,%rsp
                    20107e:    pop    %rbx
                    20107f:    pop    %rbp
                    201080:    retq  

Well, if I break it into lines:

mov    %rsp,%rbp : puts value of rsp into rbp
lea    0x4(%rsp),%rbx : put "0x4*rsp" into rbx. (*rsp = address of or rsp)
add    $0x15,%rbp : adds the integer that at "0x15" to rbp and saves the sum in 
                                                              rbp.

mov    -0x2(%rbx),%eax : moves the value that inside of ??? to eax
add    -0x4(%rbx),%eax : adds the value that inside of ??? to eax as saves the sum 
                                                                           in eax.

cmp    %eax,(%rbx): compares eax with rbx.

well, I can't really understand what "0x4(%rsp)" means, what the minus in "-0x2(%rbx)" and "-0x4(%rbx)" means..

I am trying to connect the dots here. It seems like a loop, that increases rbx or eax and then compares them.. I don't really get it though.


Solution

  • ... I can't really understand what "0x4(%rsp)" means, what the minus in "-0x2(%rbx)" and "-0x4(%rbx)" means..

    Those numbers are to be added to the value between the parenthesis, the number is a displacement component.

    In 0x4(%rsp), the true address becomes the value in the %RSP register plus 4.
    In -0x2(%rbx), the true address becomes the value in the %RBX register minus 2.

    e.g. If in mov -0x2(%rbx),%eax the %RBX register holds 100002 then the %EAX register receives the dword stored at memory address 100000.

    e.g. If in lea 0x4(%rsp),%ebx the %RSP register holds 100000 then the %EBX register receives the value 100004.


    [code was added]

    Now that you've added more code, we can try to figure out how the loop might work.

               mov    %rsp,%rsi
               callq  2014a5 <read_input>
               cmpl   $0x0,(%rsp)
               jne    201051 <func_2+0x1b>
               cmpl   $0x1,0x4(%rsp)
               je     201056 <func_2+0x20>
    201051:    callq  20146f <wrong_input>
    
    201056:    mov    %rsp,%rbp
               lea    0x4(%rsp),%rbx
               add    $0x18,%rbp
    
    201062:    mov    -0x2(%rbx),%eax
               add    -0x4(%rbx),%eax
               cmp    %eax,(%rbx)
               je     201071 <func_2+0x3b>
               callq  20146f <wrong_input>
    201071:    add    $0x2,%rbx
               cmp    %rbp,%rbx
               jne    201062 <func_2+0x2c>
    

    (-) It's unsolvable

    In order to avoid that first callq to wrong_input, the first 8 bytes at (%rsp) need to be:

    %rsp        %rbx
    v           v
    00,00,00,00,01,00,00,00
          -----------
    +++++++++++ ===========
    

    But then the first iteration of the loop will fail and do that second callq to wrong_input because:

    -----------    mov -0x2(%rbx),%eax    --> 0x00010000
    +++++++++++    add -0x4(%rbx),%eax    --> 0x00010000 + 0x00000000
    ===========    cmp %eax,(%rbx)        --> 0x00010000 <> 0x00000001
    

    (+) Think Fibonacci

    If we only consider the loop part, then we can find a sequence of integers that will pass. Here they are:

    65536, 131073, 327683, 851976, 2228245, 5832759, 144
    

    You need to look at it when stored in memory:

                first                                                 last
    %rsp        %rbx                     -->                          %rbx  %rbp
    v           v                                                     v     v
    00,00,01,00,01,00,02,00,03,00,05,00,08,00,0D,00,15,00,22,00,37,00,59,00,90,00
          -----------                                           -----------
    +++++++++++ ===========                               +++++++++++ ===========
    

    Do notice that the loop reads one word beyond the end in %rbp, therefore the input is actually six and a half dword integers!