Понимание дизассемблированного кода C: dec% eax и movl $ 0x0, -0x8 (% ebp) - PullRequest
0 голосов
/ 10 июля 2019

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

  • dec% eax: Почему регистр eax уменьшается?Каково начальное значение регистра eax?
  • movl $ 0x0, -0x8 (% ebp): Почему мы перемещаем значение 0x0 в стек?Мовл не хранит 32-битное значение (4 байта)?Если так, то почему значение хранится на 8 байтов ниже базового указателя вместо 4 байтов?

Вот разобранный двоичный файл:

Contents of section .text:
 0000 554889e5 48c745f8 00000000 905dc3    UH..H.E......]. 
Contents of section .rodata:
 0000 48656c6c 6f00                        Hello.          
Contents of section .comment:
 0000 00474343 3a202855 62756e74 7520352e  .GCC: (Ubuntu 5.
 0010 342e302d 36756275 6e747531 7e31362e  4.0-6ubuntu1~16.
 0020 30342e31 30292035 2e342e30 20323031  04.10) 5.4.0 201
 0030 36303630 3900                        60609.          
Contents of section .eh_frame:
 0000 14000000 00000000 017a5200 01781001  .........zR..x..
 0010 1b0c0708 90010000 1c000000 1c000000  ................
 0020 00000000 0f000000 00410e10 8602430d  .........A....C.
 0030 064a0c07 08000000                    .J......        

Disassembly of section .text:
0000000000000000 <my_function>:
   0:   55                      push   %ebp
   1:   48                      dec    %eax
   2:   89 e5                   mov    %esp,%ebp
   4:   48                      dec    %eax
   5:   c7 45 f8 00 00 00 00    movl   $0x0,-0x8(%ebp)
   c:   90                      nop
   d:   5d                      pop    %ebp
   e:   c3                      ret    

Вот код C:

void my_function () { 
   char* my_string = "Hello";
}

Ответы [ 2 ]

4 голосов
/ 10 июля 2019

Вы разбираете 64-битный код, как если бы это был 32-битный код. Префикс REX.W, существующий только в 64-битном коде, является инструкцией DEC EAX в 32-битном коде.

2 голосов
/ 10 июля 2019

Вы разбираете 64-битный код, как если бы это был 32-битный код.Обычно это невозможно, если вы специально не переопределите свой дизассемблер или не используете objcopy или что-то еще для копирования 64-битного машинного кода в 32-битный объектный файл ELF.

x86-64 перепрофилировали 0x40..fбайты как префиксы REX вместо 1-байтовых кодировок inc / dec.DEC EAX на самом деле является префиксом REX.W, поэтому для обычной установки указателя кадра указывается mov %rsp, %rbp.

Это также объясняет использование 8 верхних байтов красной зоны под стекомуказатель.(x86-64 System V имеет красную зону, i386 System V - нет; она будет перемещать ESP перед сохранением под ней.) И это объясняет -8 вместо -4 для указателя, потому что x86-64 имеет 8-байтовые указатели.


0 байты, потому что вы разбираете .o, который не связан.Эти 4 байта нулей будут заполнены абсолютным адресом строки компоновщиком.

GCC использует здесь mov r/m64, sign_extended_imm32 для хранения 8-байтового указателя на память, используя 32-битный абсолютный адрес в качественемедленное.

Чтобы поместить его в регистр, мы получили бы нормальный mov r32, imm32 (с неявным нулевым расширением до 64-битного) для исполняемого файла без PIE.Но этот код (со стандартным -O0 «режимом отладки») требует всего 8-байтового указателя в памяти.Он по-прежнему может использовать 32-разрядный абсолютный адрес вместо REA-относительного LEA в регистре + отдельном хранилище, но это должно быть явным расширением знака до 64-разрядного.

...