Почему выходные данные разборки NASM и dumpbin.exe отличаются для одного и того же исполняемого файла?

Вот шаги, за которыми я следовал.

1) Я взял код на ассемблере для трех разных небольших программ из книги Кипра Ирвина "Язык ассемблера для процессоров x86".

2) Я собрал, связал, чтобы создать действительный исполняемый файл без ошибок в каждом случае.

3) Для каждого из исполняемых файлов я генерировал разборки с помощью NASM

ndisasm -u -p intel add3.exe > add3_ndisasm.txt

4) В каждом случае я получал вывод разборки, используя также dumpbin.exe

dumpbin /disasm add3.exe > add3_dumpbin_disasm.txt

Удивительно, но разборка, которую я получил на шаге 4, полностью отличается от разборки на шаге 3.

Вот код сборки, который я использовал (в одном из 3 случаев).

; This program adds and subtracts 32-bit integers.
.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD
DumpRegs PROTO
.code
main PROC
mov eax,10000h ; EAX = 10000h
add eax,40000h ; EAX = 50000h
sub eax,20000h ; EAX = 30000h
call DumpRegs
INVOKE ExitProcess,0
main ENDP
END main

Вот пример разборки с шага 3 ( NDISASM)

00000000  4D                dec ebp

00000001  5A                pop edx

00000002  90                nop

00000003  0003              add [ebx],al

00000005  0000              add [eax],al

00000007  000400            add [eax+eax],al

0000000A  0000              add [eax],al

0000000C  FF                db 0xff

0000000D  FF00              inc dword [eax]

и это из шага 4 (dumpbin.exe)

Microsoft (R) COFF/PE Dumper Version 14.11.25508.2
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file add3.exe

File Type: EXECUTABLE IMAGE

  00401000: 50                 push        eax

  00401001: E8 EF 0F 00 00     call        00401FF5

  00401006: C3                 ret

  00401007: 55                 push        ebp

  00401008: 8B EC              mov         ebp,esp

  0040100A: 83 C4 E8           add         esp,0FFFFFFE8h

  0040100D: 60                 pushad

  0040100E: 80 3D 00 40 40 00  cmp         byte ptr ds:[00404000h],0
            00

  00401015: 75 05              jne         0040101C

Я взял несколько кодов инструкций из вывода шага 3 и попытался найти их в списке разборки шага 4, но не смог их найти.

5) Затем я взял шестнадцатеричный дамп исполняемого файла (используя frhed) и сравнил значения байтов в нем с выходными данными в обоих шагах.

0000  4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 b8 00 00 00 00 00 00 00 40 00 00  MZ..........ÿÿ..¸.......@..

001b  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ...........................

0036  00 00 00 00 00 00 d8 00 00 00 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 73  ......Ø.....º..´.Í!¸.LÍ!Ths

0051  69 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f 74 20 62 65 20 72 75 6e 20 69 6e 20  i program cannot be run in 

006c  44 4f 53 20 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 5b 39 0b f3 1f 58 65  DOS mode....$.......[9.ó.Xe

Значения байтов, которые я вижу на шаге 5, соответствуют значениям на шаге 3, но не шагу 4.

Чем объясняются эти различия? Я, должно быть, упускаю какую-то простую маленькую деталь где-то, что это?

1 ответ

Решение

Короткий ответ: .exe.com

Подсказка: обратите внимание на MZ подпись в виде двух первых байтов на выходе шага 5:-P

Длинный ответ:

Исполняемый файл Microsoft .exe Формат имеет больше, чем просто код. Прежде всего, он начинается со специальной подписи (инициалы создателя формата), за которой следует довольно много информации, которая описывает организацию кода.

В отличие от .com file - это просто код, то есть самый первый его байт - это то, что исполняется, когда файл загружается в память.

Первая дизассемблирование, которое вы получаете, является неправильным (да, первый - неправильным, а не вторым!), Так как он пытается начать синтаксический анализ с первого байта вместо того, чтобы перейти к реальному коду.

dumpbin достаточно умен, чтобы правильно разобрать заголовок этого .exe файл и начинается разборка фактического кода.

Решение

Если вы хотите сравнить выходные данные дизассемблирования, вы должны либо убедиться, что ваш NASM знает тип файла и правильно анализирует его заголовок, либо... упростить свою жизнь и преобразовать .exe в .com в этом случае обе операции разборки должны давать одинаковый результат (конечно, исключая возможные ошибки)

В прошлый раз я конвертировал .exe файл в .com было много лет назад с утилитой под названием exe2bin, Быстрый поиск в Интернете показывает, что это было во времена Windows XP и больше не поставляется с ОС. Хотя я не вижу причин, по которым он не работает, если вы загружаете его из какого-то места.

Общий ответ таков: ваши ожидания необоснованны.

Только специально разработанные ассемблеры и дизассемблеры со специально разработанной аппаратурой мнемоники могут справиться с этим. Это может проиллюстрировать простой пример. Предположим, у вас есть

 MOV RCX, RBX  ; Intel destination then source.

Для этой инструкции есть два возможных машинных кода. Ассемблер выбирает произвольный. Поэтому, если вы дизассемблируете и повторно соберете рабочий код, содержащий эту инструкцию, вы можете не получить обратно исходный код. Это простой пример. Как только вы перейдете к более коротким специальным кодам для AX, байтам масштабированного индекса, вариантам смещения и тому подобному, все станет намного хуже.

http://home.hccnet.nl/a.w.m.van.der.horst/ciasdis.html предоставляет такой ассемблер.

В приведенном выше примере в этой комбинации ассемблер / дизассемблер у вас есть две однозначно определенные инструкции

MOV, X| F| CX'| R| BX|

а также

MOV, X| Т | BX'| R| CX|

Таким образом, вы можете сами протестировать ассемблер, который собираетесь использовать. Если он содержит только одну инструкцию для копирования регистра BX в регистры CX, все ставки уже отключены. (предупреждение о спойлере, никто из известных ассемблеров не подойдет.)

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