Декодирование сборки из MSV C 32-битной версии (домашнее задание). Что делает неоператор? - PullRequest
2 голосов
/ 18 февраля 2020

Привет, хедз-ап, это домашнее задание. Мне дана сборка, сгенерированная MSV C 32-bit Release с оптимизацией, и я должен декодировать ее обратно в C ++. Я добавил верхнюю часть функции в строку, с которой у меня проблемы. Мои комментарии, которые я написал, пытаясь понять это.

Примечание: код предположительно генерируется из C ++. Не традиционный ASM. Примечание 2: В коде есть одна область неопределенного поведения.

Вот строки, с которыми я застрял

TheFunction:                            ; TheFunction(int* a, int s);
0F2D4670  push  ebp                     ; Push/clear/save ebp
0F2D4671  mov   ebp,esp                 ; ebp now points to top of stack
0F2D4673  push  ecx                     ; Push/clear/save ecx
0F2D4674  push  ebx                     ; Push/clear/save ebs
0F2D4675  push  esi                     ; Push/clear/save esi

0F2D4676  mov   ebx,edx                         ; ebx = int s
0F2D4678  mov   esi,1                           ; esi = 1
0F2D467D  push  edi  ; calling convention       ; Push/clear/save edi
0F2D467E  mov   edi,dword ptr [a (0F2D95E8h)]   ; edi = a[0]
0F2D4684  cmp   ebx,esi                         ; if(s < 1)
0F2D4686  jl    SomeFunction+3Ch (0F2D46ACh)    ;   Jump to return
0F2D4688  nop   dword ptr [eax+eax]             ; !! <-- No op involving dereferencing?  What does this do?
0F2D4690  mov   eax,dword ptr [edi+esi*4-4]     ; !! <-- edi is *a, while esi is 1. There is no address 
here!
..... More code but I've figured these out ....

Я более или менее понял суть функции , Это функция, которая принимает указатель на int с базовым массивом и размером. Затем он проходит через каждый элемент в массиве от последнего к первому, добавляя к каждому последующему и распечатывая его. Тем не менее, я до сих пор не выяснил детали и мне нужна помощь

Два вопроса, оба в конце фрагмента кода. Что не делает операция с указателем разыменования, и я читаю последнюю строку в том, что она пытается разыменовать что-то не в памяти?

1 Ответ

5 голосов
/ 18 февраля 2020

Инструкция nop dword ptr [eax+eax] ничего не делает. Он даже не обращается к области памяти, указанной операндом. Он буквально не выполняет никаких операций.

Это просто так, поэтому следующая инструкция выровнена по 16-байтовой границе. Вы заметите, что следующий адрес инструкции - 0F2D4690, который заканчивается 0, что означает, что он выровнен по 16 байтов. Это может улучшить производительность петель. Где-то будет инструкция, которая возвращается к 0F2D4690 как часть al oop. Эта конкретная форма инструкции NOP используется потому, что она кодирует одну инструкцию NOP в 8 байтов.

Для этой инструкции нет соответствующего кода C ++. Вы не должны пытаться представить его в своем коде C ++, просто игнорируйте его.

Также обратите внимание, что ваш комментарий для mov edi,dword ptr [a (0F2D95E8h)] неверен. Вместо edi = a[0] это просто edi = a. Переменная a вообще не является параметром, это глобальная переменная (или уровень файла c), расположенная в ячейке памяти 0F2D95E8h. Эта инструкция просто загружает значение из памяти.

...