编写的程序经编译链接之后,就可用debug等调试工具调试执行,也能看到反汇编的结果,这很便于理解“汇编指令”是如何翻译成“机器指令”的。对Windows程序,这样的工具有很多,像SoftICE、TRW、W32dasm、IDA、Hiew等。这里准备谈一下W32dasm。
;===============================================================
;例:取命令行参数,并显示到消息框中
;文件名:6.asm
.386
.model flat,stdcall
option casemap:none
include windows.inc ;常量及结构定义
include kernel32.inc ;函数原型声明
include user32.inc
includelib kernel32.lib ;用到的引入库
includelib user32.lib
.data
szCaption db "命令行参数",0
.code
start:
invoke GetCommandLine
invoke MessageBox,NULL,eax,addr szCaption,MB_OK
invoke ExitProcess,NULL
end start
---------------------------------------------------------
用到API函数:
LPTSTR GetCommandLine(VOID)
This function has no parameters.
The return value is a pointer to the command-line string for the current process.
---------------------------------------------------------
编译链接:
---------------------------------------------------------
下面使用W32dasm来反汇编6.exe。
启动W32dasm,从菜单Disassembler中选Open File to Disassemble...,从出现的对话框中选择要进行反汇编的程序,比如6.exe并打开。
+++++++++++++++++++ MENU INFORMATION ++++++++++++++++++
There Are No Menu Resources in This Application
+++++++++++++++++ DIALOG INFORMATION ++++++++++++++++++
There Are No Dialog Resources in This Application
+++++++++++++++++++ IMPORTED FUNCTIONS ++++++++++++++++++
Number of Imported Modules = 2 (decimal) ;本程序用到两个引入库
Import Module 001: KERNEL32.dll
Import Module 002: USER32.dll
+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++
Import Module 001: KERNEL32.dll ;要用到本库中下面两个函数
Addr:00002072 hint(00B6) Name: GetCommandLineA
Addr:00002064 hint(0075) Name: ExitProcess
Import Module 002: USER32.dll
Addr:00002092 hint(01BB) Name: MessageBoxA
+++++++++++++++++++ EXPORTED FUNCTIONS ++++++++++++++++++
Number of Exported Functions = 0000 (decimal)
+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
//********************** Start of Code in Object .text **************
Program Entry Point = 00401000 (6.exe File Offset:00001600)
* Reference To: KERNEL32.GetCommandLineA, Ord:00B6h
|
//******************** Program Entry Point ******** ;程序入口点
:00401000 E81D000000 Call 00401022 ;取命令行参数
:00401005 6A00 push 00000000
:00401007 680E304000 push 0040300E
:0040100C 50 push eax
:0040100D 6A00 push 00000000
* Reference To: USER32.MessageBoxA, Ord:01BBh
|
:0040100F E814000000 Call 00401028 ;显示消息框
:00401014 6A00 push 00000000
* Reference To: KERNEL32.ExitProcess, Ord:0075h
|
:00401016 E801000000 Call 0040101C ;结束程序
:0040101B CC int 03
* Referenced by a CALL at Address:
|:00401016
|
* Reference To: KERNEL32.ExitProcess, Ord:0075h
|
:0040101C FF2504204000 Jmp dword ptr [00402004] ;转到ExitProcess去执行
* Referenced by a CALL at Address:
|:00401000
|
* Reference To: KERNEL32.GetCommandLineA, Ord:00B6h
|
:00401022 FF2500204000 Jmp dword ptr [00402000] ;转到GetCommandLine去执行
* Reference To: USER32.MessageBoxA, Ord:01BBh
|
:00401028 FF250C204000 Jmp dword ptr [0040200C] ;转到MessageBoxA去执行
-----------------------------------------------------------------------
问题:为什么invoke GetCommandLine在编译时没直接翻译成Call dword ptr [00402000]而用下面的形式呢?
:00401000 E81D000000 Call 00401022 ;取命令行参数
. .
. .
. .
:00401022 FF2500204000 Jmp dword ptr [00402000] 转到GetCommandLine去执行