Нужна интерпретация 64-битной инструкции по сборке в отличие от 32-битной

Я просматриваю книгу Hacking: The Art of Exploitation, в которой используется 32-битная сборка, а моя машина 64-битная. Теперь я понимаю, что это не очень хорошо, но вот в чем вопрос.

Пока я отлаживаю эту программу,

  Reading symbols from ./a.out...
(gdb) break main
Breakpoint 1 at 0x113d: file first.c, line 6.
(gdb) run
Starting program: /home/kingvon/Desktop/asm/a.out 

Breakpoint 1, main () at first.c:6
6               for(i=0; i < 10; i++){
(gdb) x/3i $rip
=> 0x55555555513d <main+8>:     movl   $0x0,-0x4(%rbp)
   0x555555555144 <main+15>:    jmp    0x555555555156 <main+33>
   0x555555555146 <main+17>:    lea    0xeb7(%rip),%rdi        # 0x555555556004

это то, что я вижу на своей машине (64 бит),

0x55555555513d <main+8>:     movl   $0x0,-0x4(%rbp)

но в приведенном примере (32 бита) говорится:

0x55555555513d <main+8>:     mov   DWORD PTR [ebp-4],0x0

Из чтения 32-битной сборки совершенно ясно, что это должно означать, что машина переместит значение 0 в ячейку памяти, хранящуюся в регистре EBP, минус 4. Я знаю, что обе инструкции делают одно и то же, но я чувствую, что инструкция 64 не похоже на то, что на самом деле означает. Как можно интерпретировать/сформулировать инструкцию 64? Я знаю, что имена регистров отличаются на 64-битных


person raincouver    schedule 08.01.2021    source источник
comment
Основное различие между двумя инструкциями, которые вы показали, не в том, что одна из них 32-битная, а другая в 64-битная, а в том, что одна использует синтаксис AT&T, а другая — синтаксис Intel. Операнды перевернуты, а знаки процента, знаки доллара и слова «dword ptr» являются отличительными признаками.   -  person prl    schedule 08.01.2021
comment
В книге @prl также указано, что нужно установить значение intel, что я и сделал, но gdb остается на &t... Я пробовал echo "set disassembly-flavor intel" > ~/.gdbinit и проверил файл, который говорит, что он установлен на intel, но gdb продолжает печатать в at&t..... edit - опечатка в .gdbinit, теперь gdb печатает в intel   -  person raincouver    schedule 10.01.2021


Ответы (1)


Вероятно, проще всего просто создать 32-битные исполняемые файлы, чтобы вы могли более внимательно следить за книгой, с помощью gcc -m32. Не пытайтесь перенести учебник на другую ОС или ISA, пока вы учитесь на нем, это редко бывает успешным. (например, разные соглашения о вызовах, а не только разные размеры.)

А в GDB используйте set disassembly-flavor intel для дизассемблирования GAS .intel_syntax noprefix, как показано в вашей книге, вместо стандартного синтаксиса AT&T. Для objdump используйте objdump -drwC -Mintel. См. также Как удалить шум из вывода сборки GCC/clang? для получения дополнительной информации о выводе GCC.

(См. https://stackoverflow.com/tags/att/info по сравнению с https://stackoverflow.com/tags/intel_syntax/info).

Обе инструкции представляют собой хранилище двойных слов непосредственного 0 со смещением -4 относительно того, куда указывает указатель кадра. (Так реализовано i=0, потому что вы скомпилировали с отключенной оптимизацией.)

person Peter Cordes    schedule 08.01.2021
comment
Я пробовал -m32, но gcc выдает /usr/include/stdio.h:27:10: fatal error: bits/libc-header-start.h: No such file or directory 27 | #include <bits/libc-header-start.h>. - person raincouver; 08.01.2021
comment
@raincouver: так что установите пакет gcc-multilib вашего дистрибутива или как он его называет, например Arch lib32-gcc-libs. (Без этого вы можете собрать и слинковать статический исполняемый файл на чистом asm, где вы пишете свой собственный _start и не связываете никакие библиотеки, но для всего остального потребуется /usr/lib32/libc.so и так далее, и да, 32-битные заголовки даже для компиляции.) - person Peter Cordes; 08.01.2021
comment
Я установил gdb на intel и отредактировал .gdbinit на intel, но gdb просто не изменится на intel. Изменить. Я сделал опечатку в .gdbinit, теперь проблема исправлена. - person raincouver; 10.01.2021