• Aucun résultat trouvé

The dumpbin.exe /disasm Command-Line Option

Dans le document CODE WRITE GREAT (Page 158-161)

In order to write great code, you’ve got to recognize the difference between

6.3 Using Object-Code Utilities to Analyze Compiler Output

6.3.1 The Microsoft dumpbin.exe Utility

6.3.1.2 The dumpbin.exe /disasm Command-Line Option

The /disasm command-line option is the one of greatest interest. It produces a disassembled listing of the object file. As for the /all option, you shouldn’t try to disassemble an EXE file using the dumpbin.exe program. The dis-assembled listing you’ll get will be quite long and the vast majority of the code will probably be the listings of all the library routines your application calls. For example, the simple “Hello World” application generates over 5,000 lines of disassembled code. All but a small handful of those statements correspond to library routines. Wading through that amount of code will prove overwhelming to most people.

However, if you disassemble the hw.obj file rather than the executable file, here’s the output you will typically get:

Microsoft (R) COFF Binary File Dumper Version 6.00.8168 Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Dump of file hw.obj File Type: COFF OBJECT _main:

00000000: 55 push ebp 00000001: 8B EC mov ebp,esp 00000003: 68 00 00 00 00 push offset _main 00000008: E8 00 00 00 00 call 0000000D 0000000D: 83 C4 04 add esp,4 00000010: 5D pop ebp 00000011: C3 ret

Summary

D .data 26 .drectve 12 .text

If you look closely at this disassembled code, you’ll find the major problem with disassembling object files rather than executable files—most addresses in the code are relocatable addresses, which appear as $00000000 in the object code listing. As a result, you will probably have a hard time figuring out what the various assembly statements are doing. For example, in the hw.obj’s disassembled listing you see the following two statements:

00000003: 68 00 00 00 00 push offset _main 00000008: E8 00 00 00 00 call 0000000D

In fact, this code is not pushing the offset of the _main label onto the stack, and it is not calling the procedure at address $d. As you can see by looking at the object code emitted for these two instructions, the address field contains all zeros. If you run dumpbin on hw.obj and supply a /all command-line parameter, you’ll notice that this file has two relocation entries:

RELOCATIONS #2

Symbol Symbol Offset Type Applied To Index Name -- ---- --- -- 00000004 DIR32 00000000 B $SG340 00000009 REL32 00000000 8 _printf

The Offset column tells you the byte offset into the file where the relocations are to be applied. Note, in the disassembly above, that the push instruction starts at offset $3, so the actual immediate constant is at offset $4.

Similarly, the call instruction begins at offset $8, so the address of the actual routine that needs to be patched is 1 byte later, at offset $9. From the relo-cation information that dumpbin.exe outputs, you can discern the symbols associated with these relocations ($SG340 is an internal symbol that the C compiler generates for the “Hello World” string. _printf is, obviously, the name associated with the C printf function).

Cross-referencing every call and memory reference against the relocation list may seem like a pain, but at least you get symbolic names when you do this.

Consider the first few lines of the disassembled code when you apply the /disasm option to the hw.exe file:

File Type: EXECUTABLE IMAGE

00401000: 55 push ebp 00401001: 8B EC mov ebp,esp 00401003: 68 30 60 40 00 push 406030h 00401008: E8 05 00 00 00 call 00401012 0040100D: 83 C4 04 add esp,4 00401010: 5D pop ebp 00401011: C3 ret

. . .

Notice that the linker has filled in the addresses (relative to the load address for the file) of the offset $SG360 and _print labels. This may seem somewhat convenient, however, you should note that these labels (especially the _printf label) are no longer present in the file. When you are reading the disassembled output, the lack of these labels can make it very difficult to figure out which machine instructions correspond to HLL statements. This is yet another reason why you should use object files rather than executable files when running dumpbin.exe.

If you think it’s going to be a major pain to read the disassembled output of the dumpbin.exe utility, don’t get too upset. For optimization purposes, you’re often more interested in the code differences between two versions of an HLL program than you are in figuring out what each machine instruc-tion does. Therefore, you can easily determine which machine instrucinstruc-tions are affected by a change in your code by running dumpbin.exe on two versions of your object files (once before the change to the HLL code and one created afterward). For example, consider the following modification to the “Hello World” program:

#include <stdio.h>

int main( int argc, char **argv ) {

char *hwstr = "Hello World\n";

printf( hwstr );

}

Here’s the disassembly output that dumpbin.exe produces:

Microsoft (R) COFF Binary File Dumper Version 6.00.8168 Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Dump of file hw.obj File Type: COFF OBJECT _main:

00000000: 55 push ebp 00000001: 8B EC mov ebp,esp 00000003: 51 push ecx

00000004: C7 45 FC 00 00 00 mov dword ptr [ebp-4],offset _main 00

0000000B: FF 75 FC push dword ptr [ebp-4]

0000000E: E8 00 00 00 00 call 00000013 00000013: 59 pop ecx 00000014: 33 C0 xor eax,eax 00000016: C9 leave

00000017: C3 ret Summary

D .data 54 .debug$S 2A .drectve 18 .text

By comparing this output with the previous assembly output (either manually or by running one of the programs based on the Unix diff utility), you can see the effects the changes to your HLL source code have had on the emitted machine code. Section 6.6, “Comparing Output from Two Compilations,” discusses the merits of both methods.

Dans le document CODE WRITE GREAT (Page 158-161)