Что означает минус перед режимом адресации в ассемблере, например -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  

Ну, если я разобью его на строки:

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.

ну, я не очень понимаю, что означает "0x4(%rsp)", что означает минус в "-0x2(%rbx)" и "-0x4(%rbx)"..

Я пытаюсь соединить точки здесь. Это похоже на цикл, который увеличивает rbx или eax, а затем сравнивает их.. Хотя я действительно этого не понимаю.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
357
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

... Я не очень понимаю, что означает "0x4(%rsp)", что означает минус в "-0x2(%rbx)" и "-0x4(%rbx)"..

Эти числа должны быть добавлены к значению в скобках, число является компонентом смещения.

В 0x4(%rsp) истинным адресом становится значение в регистре %RSP плюс 4.
В -0x2(%rbx) истинным адресом становится значение в регистре %RBX минус 2.

например Если в mov -0x2(%rbx),%eax регистр %RBX содержит 100002, то регистр %EAX получает двойное слово, хранящееся по адресу памяти 100000.

например Если в lea 0x4(%rsp),%ebx регистр %RSP содержит 100000, то регистр %EBX получает значение 100004.


[код был добавлен]

Теперь, когда вы добавили больше кода, мы можем попытаться выяснить, как может работать цикл.

           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>

(-) Это неразрешимо

Чтобы избежать этого первого callq для неправильного ввода, первые 8 байтов в (%rsp) должны быть:

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

Но тогда первая итерация цикла завершится ошибкой и сделает вторую callq неправильной_вводной, потому что:

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

(+) Думайте о Фибоначчи

Если мы рассмотрим только часть цикла, то сможем найти последовательность целых чисел, которая пройдет. Вот они:

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

Вам нужно посмотреть на это при сохранении в памяти:

            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
      -----------                                           -----------
+++++++++++ ===========                               +++++++++++ ===========

Обратите внимание, что цикл считывает одно слово после конца в %rbp, поэтому ввод на самом деле представляет собой шесть с половиной целых чисел двойного слова!

@NoobCoder Поскольку это инструкция LEA, сам адрес хранится в регистре %RBX. Никакой загрузки из памяти! Если %RSP равно 0x2020, то %RBX получает только значение 0x2024.

Sep Roland 24.12.2020 17:47

Что вы подразумеваете под «истинный адрес становится значением»? Я не могу понять, что делает "lea 0x4(%rsp),%rbx". Он идет по адресу RSP, добавляет 4, затем переходит на новый адрес и получает его значение внутри RBX? или он фактически помещает адрес, например «0x0120» внутри RBX, в качестве значения?

NoobCoder 24.12.2020 17:51

да я знаю, что это цель LEA. А как же мов? Как вы упомянули в своем примере. Будет ли он перемещать значение внутри адреса?

NoobCoder 24.12.2020 17:53

@NoobCoder Инструкция, в которой используются круглые скобки, относится к некоторой ячейке памяти. Как только все компоненты адреса собраны вместе, мы получаем истинный адрес. Затем вступает в действие инструкция. Если это LEA, мы просто используем значение адреса, если это MOV, мы читаем или записываем что-то из или в память.

Sep Roland 24.12.2020 17:57

@NoobCoder В вашем фрагменте кода нет цикла! Для этого вам понадобится какая-то инструкция перехода, скорее всего, условный переход ниже инструкции CMP.

Sep Roland 24.12.2020 17:59

да, у меня есть условный переход, я просто не написал его здесь. Мне все еще довольно сложно понять, что делает этот цикл. Я имею в виду, что я всегда пытаюсь сравнить его с другим языком, таким как C или JAVA, и «перевести» его, но я не могу понять, что здесь происходит. Он сразу возвращается к -0x2(%rbx),%eax

NoobCoder 24.12.2020 18:08

@NoobCoder Разве перед этим фрагментом не было push %rbp?

Sep Roland 24.12.2020 18:12

Я добавил полный код. Моя цель здесь - найти правильный ввод (6 целых чисел). Я обнаружил, что первый должен быть «1», потому что первый CMP равен 0x1. Но потом он начинает зацикливаться, и я не могу найти формулу, по которой он работает.

NoobCoder 24.12.2020 18:29

Другие вопросы по теме