2

这是我遵循的步骤。

1) 我从 Kip Irvine 的《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 步完全不同。

这是我使用的汇编代码(在三种情况之一中)。

; 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 不匹配。

是什么解释了这些差异?我一定是在某处遗漏了一些简单的小细节,这是什么?

4

2 回答 2

3

简答: .exe.com

提示:注意MZ签名是步骤 5 输出中的两个前字节:-P

长答案:

微软的可执行.exe格式不仅仅是代码。首先,它以一个特殊的签名(格式创建者的首字母)开头,然后是描述代码组织的大量信息。

相反,.com文件只是一个代码,这意味着文件的第一个字节是文件加载到内存后执行的内容。

您得到的第一个反汇编是错误的(是的,第一个是错误的,而不是第二个!),因为它试图从第一个字节开始解析,而不是跳到实际代码。

dumpbin足够智能,可以正确解析该.exe文件的标题并开始反汇编实际代码。

解决方案

如果您想比较反汇编输出,您要么必须确保您的 NASM 知道文件的类型并正确解析其标题,要么...简化您的生活并将其转换.exe为 a.com在这种情况下,两个反汇编操作都应该产生相同的输出(当然,排除潜在的错误)

上一次我将.exe文件转换为 a.com是多年前使用名为exe2bin. 在线快速搜索显示,这是在 Windows XP 时代,并且不再随操作系统一起提供。虽然我认为如果你从某个地方下载它,它没有理由不起作用。

于 2018-01-27T09:05:43.530 回答
0

一个普遍的答案是你的期望是不合理的。

只有专门设计的协作汇编器和反汇编器具有专门设计的助记符才能处理此问题。一个简单的例子可以说明这一点。假设你有

 MOV RCX, RBX  ; Intel destination then source.

该指令有两种可能的机器代码。汇编器选择任意一个。因此,如果您反汇编并重新组装包含该指令的工作代码,您可能无法取回原始代码。这是一个简单的例子。一旦您为 AX、缩放索引字节、偏移选择等使用较短的特殊代码,情况就会变得更糟。

http://home.hccnet.nl/awmvan.der.horst/ciasdis.html 提供了这样一个汇编程序。

在上面这个汇编器/反汇编器组合的示例中,您有两个明确定义的指令

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

MOV, X| T| BX'| 右| CX|

所以你可以测试你打算自己使用的汇编器。如果它只包含一条将 BX 寄存器复制到 CX 寄存器的指令,则所有赌注都已关闭。(剧透警告,众所周知的汇编程序都不会这样做。)

于 2020-05-07T11:57:27.787 回答