Win32汇编教程(基础)

汇编语言基础win32

一、引言

Win32应用程序一般使用C语言编程,但是在某些需要进行深层编程的情况下,例如Win32应用程序执行机制分析、病毒清除、加密解密等深层编程,或者对于某些速度要求较高的程序,需要使用汇编语言(甚至机器语言)直接编写Win32应用程序。Win32应用程序虽然和其他32位应用程序(例如32位保护模式DOS 程序)一样可以使用386汇编语言和保护模式编程,但是Win32应用程序的执行机制与其他32位应用程序有一定的差别,例如消息循环、动态链接等,Win32汇编语言也有其特殊的编程方式。目前国内极少看到有关Win32汇编语言的资料,市面上的汇编语言书籍一般只介绍DOS实模式汇编语言和386保护模式汇编语言,金山公司的《深入Windows编程》一书虽然介绍了使用汇编语言写Windows应用程序的方法,可惜该书只介绍了Win16汇编语言。为了使大家能对Win32汇编语言的基本编程方法有一定的了解,近日得闲,笔者编写了本教程,旨在抛砖引玉,如果本教程能够带领你走进神秘的Win32汇编语言世界,笔者心愿足矣。使用本教程,要求读者具有C语言编写Win32应用程序(Win32SDK编程)的基础。

二、进行Win32汇编语言编程的基本软件

进行Win32汇编语言编程,应该准备下列基本软件:

1、MASM 6.11以上版本的汇编器

MASM是Microsoft公司的汇编器,这是最基本的软件,必需MASM 6.11以上版本才能够汇编Win32汇编语言源程序。不过进行Win32汇编语言编程不必要全套的MASM 6.11,只要一个ML.EXE文件就可以了,Windows 95 DDK中带有MASM 6.11c的ML.EXE文

件,Windows 98 DDK中带有MASM 6.11d的ML.EXE文件,都可以使用。Turbo MASM 5.0(TASM)是Borland公司的汇编器,也可以用来汇编Win32汇编语言源程序,但是TASM的部分语法与MASM不同,用于MASM的Win32汇编语言源程序可能需要修改后才能用TASM汇编。本教程中的所有Win32汇编语言源程序都基于MASM。

2、Win32SDK

进行Win32汇编语言编程需要用到Win32SDK中的资源编译器(RC.EXE)和连接器(LINK.EXE),还需要用到Win32SDK中的引入库文件(KERNEL32.LIB、USER32.LIB、GDI32.LIB等)。如果没有Win32SDK,Platform SDK也可以,还可以安装Visual C++ 2.0以上版本的Visual C++,笔者使用的是Visual C++ 6.0。Borland C++ 4.0以上版本的Borland C++也可以使用,只是资源编译器和连接器的

文件名不同,分别是BRC.EXE(BRC32.EXE)和TLINK.EXE(TLINK32.EXE),选项也不尽相同,另外Borland C++不支持COFF格式的OBJ文件,汇编时不能使用/coff选项。

3、汇编语言编辑器

一个普通的文本编辑器,用于编辑Win32汇编语言源程序。EDIT、PWB等都可以,Visual C++等编程语言中的编辑器也可以,甚至WORD、WPS 97等可以编

辑文本文件的字处理软件都可以,不过笔者推荐使用ASMEDIT,这是一个专用的汇编语言编辑

器,效果非常好。Win32汇编语言一般使用命令行方式汇编连接,经过一定的设置也可以在某些集成

环境(PWB、Visual C++、ASMEDIT等)下汇编连接,还可以使用NMAKE工具,不过本教程中只使用命令行方式汇编连接,也不使用NMAKE工具。

三、ANSI字符集API与UNICODE字符集API

Win32 API中凡是与字符有关的API都有两种不同的类型:ANSI字符集API和UNICODE字符集API,分别对应ANSI字符和UNICODE字符,Windows NT支持两种类型的API,Windows 95/98只支持ANSI字符集API。在WINDOWS.H 头文件和其他Win32 API定义

头文件中,凡是与字符有关的API都有两种不同的定义,ANSI字符集API以API 名称加字符“A”表示,UNICODE字符集API以API名称加字符“W”表示,并使用条件编译和宏定义实现自动根据当前字符集使用对应的API定义,例如GetModuleHandle函数的定义(包括在WINBASE.H头文件中):

WINBASEAPI

HMODULE

WINAPI

GetModuleHandleA(

LPCSTR lpModuleName

);

WINBASEAPI

HMODULE

WINAPI

GetModuleHandleW(

LPCWSTR lpModuleName

);

#ifdef UNICODE

#def ine GetModuleHandle GetModuleHandleW

#else

#def ine GetModuleHandle GetModuleHandleA

#endif // !UNICODE

与字符有关的数据结构也有类似的定义。本教程考虑到汇编语言使用条件汇编会导致不太直观,全部使用ANSI字符集API,这样也可以保证在Windows 95/98和Windows NT环境下的兼容性,所以本教程中许多API名称和数据结构的名称都加有“A”字符,读者可以方便地改用UNICODE字符集API。

四、一个简单的Win32汇编语言程序

读者可能一听到“汇编语言”四个字就觉得十分头疼!汇编语言给人的第一印象就

是一大堆难以看懂又不直观的指令,而且不结构化,大量的标号、无条件跳转指令(JMP)和条件跳转指令让你难以看懂程序;过程(或者函数)的调用参数传递又不直观,要么直接使用寄存器传递参数,不符合结构化程序设计原则;要么使用堆栈传递参数,又不能有效地检验参数类型……想必Win32汇编语言更麻烦吧!还好,MASM 6.0以上版本的汇编器提供了很多结构化汇编语言伪指令,可以方便地实现汇编语言结构化程序设计,当你看完本教程以后,你可能会感觉到:Win32汇编语言并不比C语言麻烦多少。(如果读者看不懂本教程中的汇编语言源程序也不要紧,可以对照MASM 6.11的帮助看)和C语言Win32编程需要WINDOWS.H头文件和其他Win32 API定义头文件定义常量、数据结构和API 一样,Win32汇编语言也需要包含文件(INC文件)定义常量、数据结构和API。不过笔者找了很长时间也没有找到一个完整的可用于Win32汇编语言的WINDOWS.INC文件或者WIN32.INC文件(倒是找到了用于Win16汇编语言的WINDOWS.INC文件),Turbo MASM 5.0中提供的WIN32.INC文件也不完整,只能用于自带的WAP32例子程序,而且与MASM 6.11不太兼容(听说NASM中有完整的WIN32.INC文件,可惜没有找到,也不知道与MASM 6.11是否兼容)。笔者只好自己定义常量、数据结构和API(根据WINDOWS.H头文件和其他Win32 API定义头文件定义),不过这倒

带来了不少好处——可以更好地了解Win32汇编语言的编程方法和原理。笔者编写了一个简单的Win32汇编语言程序,该程序的功能很简单:在屏幕上显示一个消息框。本程序只调用了两个API函数:MessageBox函数和ExitProcess函数,程序如下:

包含文件(MSGBOX.INC):

UINT TYPEDEF DWORD

LPSTR TYPEDEF PTR BYTE

LPCSTR TYPEDEF LPSTR

PVOID TYPEDEF PTR

HANDLE TYPEDEF PVOID

HWND TYPEDEF HANDLE

MB_ICONINFORMATION = 00000040h

MB_OK = 00000000h

MessageBoxA PROTO stdcall, :HWND,:LPCSTR,:LPCSTR,:UINT

ExitProcess PROTO stdcall, :UINT

源程序(MSGBOX.ASM):

.386p

.MODEL flat,stdcall

INCLUDE MSGBOX.INC

.STACK 4096

.DATA

WindowTitle BYTE 'MsgBox',0

Message1 BYTE 'This is a simple MessageBox

Win32 application.',0

.CODE

_start:

INVOKE MessageBoxA,0,ADDR Message1,ADDR WindowTitle,

MB_ICONINFORMATION or MB_OK

INVOKE ExitProcess,0

PUBLIC _start

END

汇编连接本程序的命令如下:

ml /c /coff /Cp msgbox.asm

link /subsystem:windows /entry:_start msgbox.obj kernel32.lib user32.lib

汇编命令中的/c选项表示只汇编,不自动连接;/coff选项表示生成COFF格式的OBJ文件(如果使用Borland的连接器不能使用/coff参数);/Cp选项表示标识符区分大小写。连接命令中/subsystem:windows选项表示连接器生成普通Windows可执行文件;/entry:_start选项表示程序入口点是_start标识符。连接时连接KERNEL32.LIB和USER32.LIB引入库。运行汇编连接后生成的MSGBOX.EXE文件,屏幕上将显示出一个消息框,消息框的标题是“MsgBox”,消息框中的字符串是“This is a simple MessageBox Win32 application.”。Win32汇编语言源程序应该由.386p伪指令和.MODEL flat,stdcall伪指令开始,指示汇编器汇编386保护模式指令,并使用平坦内存模式(Win32内存模式)和stdcall 函数调用方式(Win32标准函数调用方式)。PROTO伪指令定义函数原型(与C 语言中函数原型的定义相似),可以定义函数名、调用方式和参数,INVOKE伪指令调用由PROTO伪指令定义的函数,可以方便地传递参数和检查参数类型。MSGBOX.INC文件中使用PROTO伪指令定义API函数,MSGBOX.ASM文件中使用INVOKE伪指令调用API函数,可见MASM 6.0以上版本的汇编器提供的结构化汇编语言伪指令大大简化了Win32汇编语言编程(本程序一条汇编语言指令也没有用到)。本程序调用了MessageBox函数显示消息框以后,调用了ExitProcess函数终止程序的执行,ExitProcess函数的作用是终止当前进程。

五、显示一个窗口的Win32汇编语言程序

学习过Win32SDK编程的读者编写的第一个应用程序可能就是显示一个窗口的C

语言程序,笔者也编写了这样一个C语言程序,该程序文件名为SIMPLE.C,程序如下:

#include

static char szWindowClass[]="SIMPLE";

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM

lParam);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)

{

WNDCLASSEXA wcex;

HWND hWnd;

MSG msg;

if(!hPrevInstance)

{

wcex.cbSize=sizeof(WNDCLASSEXA);

wcex.style=CS_HREDRAW|CS_VREDRAW;

wcex.cbClsExtra=0;

wcex.cbWndExtra=0;

wcex.lpfnWndProc=WndProc;

wcex.hInstance=hInstance;

wcex.hIcon=LoadIconA(hInstance,IDI_APPLICATION);

wcex.hCursor=LoadCursorA(0,IDC_ARROW);

wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);

wcex.lpszMenuName=NULL;

wcex.lpszClassName=szWindowClass;

wcex.hIconSm=LoadIconA(hInstance,IDI_APPLICATION);

if(!RegisterClassExA(&wcex)) return FALSE;

}

hWnd=CreateWindowExA(0,szWindowClass,"SIMPLE",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT,

CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,

0,0,hInstance,NULL);

if(!hWnd) return FALSE;

ShowWindow(hWnd,nShowCmd);

UpdateWindow(hWnd);

while(GetMessageA(&msg,0,0,0))

{

TranslateMessage(&msg);

DispatchMessageA(&msg);

}

return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM

lParam)

{

HDC hDC;

PAINTSTRUCT ps;

switch(message)

{

case WM_PAINT:

hDC=BeginPaint(hWnd,&ps);

EndPaint(hWnd,&ps);

return 0;

case WM_DESTROY:

PostQuitMessage(0);

return 0;

default:

return DefWindowProcA(hWnd,message,wParam,lParam);

}

return -1;

}

本程序与一般的显示一个窗口的C语言程序基本相同,只是只使用ANSI字符集。现在笔者用Win32汇编语言程序实现本程序的功能,程序如下:

包含文件(SIMPLE.INC):

UINT TYPEDEF DWORD

LONG TYPEDEF DWORD

LPSTR TYPEDEF PTR BYTE

LPCSTR TYPEDEF LPSTR

PVOID TYPEDEF PTR

LPVOID TYPEDEF PVOID

HANDLE TYPEDEF PVOID

HINSTANCE TYPEDEF HANDLE

HWND TYPEDEF HANDLE

HMENU TYPEDEF HANDLE

HDC TYPEDEF HANDLE

HGDIOBJ TYPEDEF HANDLE

HICON TYPEDEF HANDLE

HCURSOR TYPEDEF HANDLE

HBRUSH TYPEDEF HANDLE tagWNDCLASSEXA STRUCT

cbSize UINT ?

style UINT ?

lpfnWndProc DWORD ?

cbClsExtra DWORD ?

cbWndExtra DWORD ?

hInstance DWORD ?

hIcon DWORD ?

hCursor DWORD ?

hbrBackground DWORD ? lpszMenuName DWORD ? lpszClassName DWORD ?

hIconSm DWORD ?

tagWNDCLASSEXA ENDS WNDCLASSEXA TYPEDEF tagWNDCLASSEXA tagPOINT STRUCT

x LONG ?

y LONG ?

tagPOINT ENDS

POINT TYPEDEF tagPOINT

tagMSG STRUCT

message UINT ?

wParam DWORD ?

lParam DWORD ?

time DWORD ?

pt POINT <>

tagMSG ENDS

MSG TYPEDEF tagMSG

LPMSG TYPEDEF PTR MSG

tagRECT STRUCT

left LONG ?

top LONG ?

right LONG ?

bottom LONG ?

tagRECT ENDS

RECT TYPEDEF tagRECT

tagPAINTSTRUCT STRUCT

hdc DWORD ?

fErase DWORD ?

rcPaint RECT <>

fRestore DWORD ?

fIncUpdate DWORD ?

rgbReserved BYTE 32 DUP(?)

tagPAINTSTRUCT ENDS

PAINTSTRUCT TYPEDEF tagPAINTSTRUCT

LPPAINTSTRUCT TYPEDEF PTR PAINTSTRUCT

NULL = 0

TRUE = 0ffffffffh

FALSE = 0

SW_SHOWDEFAULT = 10

CS_HREDRAW = 0002h

CS_VREDRAW = 0001h

IDI_APPLICATION = 32512

IDC_ARROW = 32512

COLOR_WINDOW = 5

WS_OVERLAPPEDWINDOW = 00cf0000h

CW_USEDEFAULT = 80000000h

WM_PAINT = 000fh

WM_DESTROY = 0002h

GetModuleHandleA PROTO stdcall, :LPCSTR

GetCommandLineA PROTO stdcall

ExitProcess PROTO stdcall, :UINT

LoadIconA PROTO stdcall, :HINSTANCE,:LPCSTR

LoadCursorA PROTO stdcall, :HINSTANCE,:LPCSTR

RegisterClassExA PROTO stdcall, :PTR WNDCLASSEXA CreateWindowExA PROTO stdcall, :DWORD,:LPCSTR,:LPCSTR,:DWORD,: DWORD,:DWORD,:DWORD,:DWORD,:HWND,:HMENU,:HINSTANCE,:LPVOID

ShowWindow PROTO stdcall, :HWND,:DWORD

UpdateWindow PROTO stdcall, :HWND

GetMessageA PROTO stdcall, :LPMSG,:HWND,:UINT,:UINT TranslateMessage PROTO stdcall, :PTR MSG

DispatchMessageA PROTO stdcall, :PTR MSG

BeginPaint PROTO stdcall, :HWND,:LPPAINTSTRUCT

EndPaint PROTO stdcall, :HWND,:PTR PAINTSTRUCT

PostQuitMessage PROTO stdcall, :DWORD

DefWindowProcA PROTO stdcall, :HWND,:UINT,:DWORD,:DWORD

源程序(SIMPLE.ASM):

.386p

.MODEL flat,stdcall

INCLUDE SIMPLE.INC

WinMain PROTO stdcall, :HINSTANCE,:HINSTANCE,:LPSTR,:

DWORD

.STACK 4096

.DATA

WindowClass BYTE 'SIMPLE',0

WindowTitle BYTE 'SIMPLE',0

hInst1 HINSTANCE 0

lpCmdLine1 LPSTR 0

.CODE

_start:

INVOKE GetModuleHandleA,NULL

mov hInst1,eax

INVOKE GetCommandLineA

mov lpCmdLine1,eax

INVOKE WinMain,hInst1,NULL,lpCmdLine1,SW_SHOWDEFAULT

INVOKE ExitProcess,eax

WinMain PROC hInst:HINSTANCE,hPrevInst:HINSTANCE,lpCmdLine:LPSTR, nShowCmd:DWORD

LOCAL wcex:WNDCLASSEXA

LOCAL hWnd:HWND

LOCAL msg:MSG

.IF !hPrevInst

mov wcex.cbSize,SIZEOF WNDCLASSEXA

mov wcex.style,CS_HREDRAW or CS_VREDRAW

mov wcex.cbClsExtra,0

mov wcex.cbWndExtra,0

mov wcex.lpfnWndProc,OFFSET WndProc

mov eax,hInst

mov wcex.hInstance,eax

INVOKE LoadIconA,hInst,IDI_APPLICATION

mov wcex.hIcon,eax

INVOKE LoadCursorA,0,IDC_ARROW

mov wcex.hCursor,eax

mov wcex.hbrBackground,COLOR_WINDOW+1

mov wcex.lpszMenuName,NULL

mov wcex.lpszClassName,OFFSET WindowClass

INVOKE LoadIconA,hInst,IDI_APPLICATION

mov wcex.hIconSm,eax

INVOKE RegisterClassExA,ADDR wcex

.IF !eax

mov eax,FALSE

ret

.ENDIF

.ENDIF

INVOKE CreateWindowExA,0,ADDR WindowClass,ADDR WindowTitle,

WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAU LT,

CW_USEDEFAULT,0,0,hInst,NULL

mov hWnd,eax

.IF !eax

mov eax,FALSE

ret

.ENDIF

INVOKE ShowWindow,hWnd,nShowCmd

INVOKE UpdateWindow,hWnd

.WHILE TRUE

INVOKE GetMessageA,ADDR msg,0,0,0

.BREAK .IF !eax

INVOKE TranslateMessage,ADDR msg

INVOKE DispatchMessageA,ADDR msg

.ENDW

mov eax,msg.wParam

ret

WinMain ENDP

WndProc PROC hWnd:HWND,message:UINT,wParam:DWORD,lParam:DWORD LOCAL hDC:HDC

LOCAL ps:PAINTSTRUCT

.IF message==WM_PAINT

INVOKE BeginPaint,hWnd,ADDR ps

mov hDC,eax

INVOKE EndPaint,hWnd,ADDR ps

mov eax,0

ret

.ELSEIF message==WM_DESTROY

INVOKE PostQuitMessage,0

mov eax,0

ret

.ELSE

INVOKE DefWindowProcA,hWnd,message,wParam,lParam

ret

.ENDIF

mov eax,0ffffffffh

ret

WndProc ENDP

PUBLIC _start

END

汇编连接本程序的命令如下:

ml /c /coff /Cp simple.asm

link /subsystem:windows /entry:_start simple.obj kernel32.lib user32.lib

gdi32.lib

运行汇编连接后生成的SIMPLE.EXE文件,屏幕上将显示出一个标准的窗口,窗口的标题是“SIMPLE”。学习过Win32SDK编程的读者都知道,Win32应用程序的入口点是WinMain函数,实际上WinMain函数是被C语言的初始化和结束代码调用的,Win32应用程序的真正入口点和DOS应用程序没有什么区别,都是在文件头中指定的应用程序起始点。Win32汇编语言没有C语言的初始化和结束代码,必须自己编写初始化和结束代码调用

WinMain函数(过程),WinMain函数的原型是:

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd);

WinMain函数有4个参数,分别是:

hInstance——应用程序当前实例的句柄,可以通过调用GetModuleHandle函数

获取.

hPrevInstance——应用程序前一个实例的句柄,Win32中当前地址空间中不会有应用程序的其他实例在运行,该参数通常设置为NULL(提供该参数只是便于移植Win16应用程序源程序)。

lpCmdLine——命令行参数,可以通过调用GetCommandLine函数获取。nShowCmd——主窗口的显示状态,可以设置成SW_SHOWDEFAULT(缺省状态)。本程序的初始化和结束代码如下:

INVOKE GetModuleHandleA,NULL

mov hInst1,eax

INVOKE GetCommandLineA

mov lpCmdLine1,eax

INVOKE WinMain,hInst1,NULL,lpCmdLine1,SW_SHOWDEFAULT

INVOKE ExitProcess,eax

Win32标准函数调用方式,函数返回值通过EAX寄存器返回。可见本程序的初始化和结束代码很简单,只是调用GetModuleHandle函数获取应用程序当前实例的句柄,调用GetCommandLine函数获取命令行参数,然后调用WinMain函数(过程),WinMain函数返回后调用ExitProcess函数终止程序的执行。将本程序与SIMPLE.C程序比较,可以看出程序结构十分相似,本程序大量使用了MASM

6.0以上版本的汇编器提供的结构化汇编语言伪指令,并不比C语言麻烦多少。

六、资源在Win32汇编语言程序中的使用

资源在Win32应用程序中是很重要的,笔者编写了一个使用资源的C语言程序,该程序实现了菜单和一个“About”对话框,程序如下:

源程序(GENERIC.C):

#include

#include "resource.h"

static HINSTANCE hInst;

static char szWindowClass[]="GENERIC";

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM

lParam);

BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM

lParam);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)

{

WNDCLASSEXA wcex;

HWND hWnd;

MSG msg;

hInst=hInstance;

if(!hPrevInstance)

{

wcex.cbSize=sizeof(WNDCLASSEXA);

wcex.style=CS_HREDRAW|CS_VREDRAW;

wcex.cbClsExtra=0;

wcex.cbWndExtra=0;

wcex.lpfnWndProc=WndProc;

wcex.hInstance=hInstance;

wcex.hIcon=LoadIconA(hInstance,IDI_APPLICATION);

wcex.hCursor=LoadCursorA(0,IDC_ARROW);

wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);

wcex.lpszMenuName=MAKEINTRESOURCE(IDR_MAINMENU);

wcex.lpszClassName=szWindowClass;

wcex.hIconSm=LoadIconA(hInstance,IDI_APPLICATION);

if(!RegisterClassExA(&wcex)) return FALSE;

}

hWnd=CreateWindowExA(0,szWindowClass,"Generic",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT,

CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,

0,0,hInstance,NULL);

if(!hWnd) return FALSE;

ShowWindow(hWnd,nShowCmd);

UpdateWindow(hWnd);

while(GetMessageA(&msg,0,0,0))

{

TranslateMessage(&msg);

DispatchMessageA(&msg);

}

return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM

lParam)

{

HDC hDC;

PAINTSTRUCT ps;

switch(message)

{

case WM_COMMAND:

switch(LOWORD(wParam))

{

case IDM_EXIT:

SendMessageA(hWnd,WM_CLOSE,0,0);

return 0;

case IDM_ABOUT:

DialogBoxParamA(hInst,MAKEINTRESOURCE(IDD_ABOUT),

hWnd,(DLGPROC)AboutDlgProc,0);

return 0;

default:

return DefWindowProcA(hWnd,message,wParam,lParam)

;

}

case WM_PAINT:

hDC=BeginPaint(hWnd,&ps);

EndPaint(hWnd,&ps);

return 0;

case WM_DESTROY:

PostQuitMessage(0);

return 0;

default:

return DefWindowProcA(hWnd,message,wParam,lParam);

}

return -1;

}

BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM

lParam)

{

switch(message)

{

case WM_INITDIALOG:

return TRUE;

case WM_COMMAND:

if((LOWORD(wParam)==IDOK)||(LOWORD(wParam)==IDCANCEL))

{

EndDialog(hDlg,LOWORD(wParam));

return TRUE;

}

return FALSE;

default:

return FALSE;

}

}

资源源文件(GENERIC.RC,使用Visual C++ 6.0建立):

//Microsoft Developer Studio generated resource script.

//

#include "resource.h"

#def ine APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////////////// /////

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

//////////////////////////////////////////////////////////////////////// /////

#undef APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////////////// /////

// Chinese (P.R.C.) resources

#if !def ined(AFX_RESOURCE_DLL) || def ined(AFX_TARG_CHS) #ifdef _WIN32

LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

#pragma code_page(936)

#endif //_WIN32

//////////////////////////////////////////////////////////////////////// /////

//

// Menu

//

IDR_MAINMENU MENU DISCARDABLE

BEGIN

POPUP "&File"

BEGIN

MENUITEM "&Exit", IDM_EXIT

END

POPUP "&Help"

BEGIN

MENUITEM "&About...", IDM_ABOUT

END

END

#ifdef APSTUDIO_INVOKED

////////////////////////////////////////////////////////////////////////

/////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE DISCARDABLE

BEGIN

"resource.h\0"

END

2 TEXTINCLUDE DISCARDABLE

BEGIN

"#include ""afxres.h""\r\n"

"\0"

END

3 TEXTINCLUDE DISCARDABLE

BEGIN

"\r\n"

"\0"

END

#endif // APSTUDIO_INVOKED

////////////////////////////////////////////////////////////////////////

/////

//

// Dialog

//

IDD_ABOUT DIALOG DISCARDABLE 0, 0, 92, 65

STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU

CAPTION "About"

FONT 9, "宋体"

BEGIN

LTEXT "Generic V1.0",IDC_STATIC1,20,10,50,10 DEFPUSHBUTTON "OK",IDOK,20,40,50,15

END

//////////////////////////////////////////////////////////////////////// /////

//

// DESIGNINFO

//

#ifdef APSTUDIO_INVOKED

GUIDELINES DESIGNINFO DISCARDABLE

BEGIN

IDD_ABOUT, DIALOG

BEGIN

LEFTMARGIN, 7

RIGHTMARGIN, 85

TOPMARGIN, 7

BOTTOMMARGIN, 58

END

END

#endif // APSTUDIO_INVOKED

#endif // Chinese (P.R.C.) resources

//////////////////////////////////////////////////////////////////////// /////

#ifndef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////////////// /////

//

// Generated from the TEXTINCLUDE 3 resource.

//

//////////////////////////////////////////////////////////////////////// /////

#endif // not APSTUDIO_INVOKED

资源头文件(RESOURCE.H,Visual C++ 6.0自动建立):

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include f ile.

// Used by GENERIC.rc

//

#def ine IDR_MAINMENU 101

#def ine IDD_ABOUT 102

#def ine IDC_STATIC1 1000

#def ine IDM_EXIT 40001

#def ine IDM_ABOUT 40002

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#def ine _APS_NEXT_RESOURCE_VALUE 103

#def ine _APS_NEXT_COMMAND_VALUE 40003

#def ine _APS_NEXT_CONTROL_VALUE 1001

#def ine _APS_NEXT_SYMED_VALUE 101

#endif

#endif

本程序与一般Win32编程资料中的GENERIC程序基本相同,只是只使用ANSI 字符集。

现在笔者用Win32汇编语言程序实现本程序的功能,程序如下:

包含文件(GENERIC.INC):

UINT TYPEDEF DWORD

LONG TYPEDEF DWORD

LPSTR TYPEDEF PTR BYTE

LPCSTR TYPEDEF LPSTR

PVOID TYPEDEF PTR

LPVOID TYPEDEF PVOID

HANDLE TYPEDEF PVOID

HINSTANCE TYPEDEF HANDLE

HWND TYPEDEF HANDLE

HMENU TYPEDEF HANDLE

HDC TYPEDEF HANDLE

HGDIOBJ TYPEDEF HANDLE

HICON TYPEDEF HANDLE

HCURSOR TYPEDEF HANDLE

HBRUSH TYPEDEF HANDLE

tagWNDCLASSEXA STRUCT

cbSize UINT ?

style UINT ?

lpfnWndProc DWORD ?

cbClsExtra DWORD ?

cbWndExtra DWORD ?

hInstance DWORD ?

hIcon DWORD ?

hCursor DWORD ?

hbrBackground DWORD ? lpszMenuName DWORD ? lpszClassName DWORD ?

hIconSm DWORD ?

tagWNDCLASSEXA ENDS WNDCLASSEXA TYPEDEF tagWNDCLASSEXA tagPOINT STRUCT

x LONG ?

y LONG ?

tagPOINT ENDS

POINT TYPEDEF tagPOINT

tagMSG STRUCT

message UINT ?

wParam DWORD ?

lParam DWORD ?

time DWORD ?

pt POINT <>

tagMSG ENDS

MSG TYPEDEF tagMSG

LPMSG TYPEDEF PTR MSG

tagRECT STRUCT

left LONG ?

top LONG ?

right LONG ?

bottom LONG ?

tagRECT ENDS

RECT TYPEDEF tagRECT tagPAINTSTRUCT STRUCT

hdc DWORD ?

fErase DWORD ?

rcPaint RECT <>

fRestore DWORD ?

fIncUpdate DWORD ?

rgbReserved BYTE 32 DUP(?) tagPAINTSTRUCT ENDS

PAINTSTRUCT TYPEDEF tagPAINTSTRUCT LPPAINTSTRUCT TYPEDEF PTR PAINTSTRUCT NULL = 0

TRUE = 0ffffffffh

FALSE = 0

SW_SHOWDEFAULT = 10

CS_HREDRAW = 0002h

CS_VREDRAW = 0001h

IDI_APPLICATION = 32512

IDC_ARROW = 32512

COLOR_WINDOW = 5

WS_OVERLAPPEDWINDOW = 00cf0000h

CW_USEDEFAULT = 80000000h

WM_COMMAND = 0111h

WM_CLOSE = 0010h

WM_PAINT = 000fh

WM_DESTROY = 0002h

WM_INITDIALOG = 0110h

IDOK = 1

IDCANCEL = 2

GetModuleHandleA PROTO stdcall, :LPCSTR GetCommandLineA PROTO stdcall

ExitProcess PROTO stdcall, :UINT

LoadIconA PROTO stdcall, :HINSTANCE,:LPCSTR LoadCursorA PROTO stdcall, :HINSTANCE,:LPCSTR

汇编制作木马

现在很多单位都采用单独的计算机来存放重要的涉密文件。然而如果涉密文件被盗,不仅会带来严重的经济损失,窃密者还可能逍遥法外。为了解决这个问题,我们需要对涉密文件采取某些措施:如绑定木马,在窃密者在得手后木马能自动执行,并记录下窃密者的相关信息,最后及时通知监控端。上面所采取的措施,我们称为网络跟踪技术。本文所要讲述的汇编木马,就经常应用在跟踪技术中。 举个例子:在一涉密.Doc文件中绑定一个.Exe木马。如果木马功能复杂,并且是在VC等编译环境下生成,那它的体积至少有几十K,再加上.Doc文件自身的数据量就非常可观了。一个大的.Doc文件会引起窃密者的怀疑,我们的跟踪也就达不到效果。因此,我们势必要设法在不影响最终目的的前提下,尽量减小木马文件的体积。办法可能不止一个,而我采用的是编写汇编木马的方式。当然,研究的平台都是在Windows2000以上的操作系统中。 Win32汇编木马设计思路 完整的汇编木马又称为“小马”,原因有两个:一是它体积小,只有几K;二是它的功能仅仅是反向连接攻击端,从攻击端下载并执行真正的功能复杂的木马(大马)。为了便于大家理解,本文将不关心“大马”的功能实现,重点是提出汇编木马的设计思路,并尽量从基础的角度进行讨论。 汇编木马的设计围绕4个重要的技术指标:体积小、防杀、突破防火墙与进程隐藏、拖动并执行“大马”, 下面逐一介绍: 1、体积小。常规木马大多用高级语言编写,在集成环境下编译生成。虽然

实现方便,但是生成的.Exe文件体积较大。对于汇编木马,我们采用Win32汇编来实现,使得.Exe文件体积控制在几K。 2、防杀。为了避免被诺顿、卡巴斯基、江民等主流杀毒软件所识别,木马文件一定要进行可靠的加壳处理。根据经验,一般我们选用最新的ASProtect,加壳后的.Exe文件生存能力一般比较强。如果需要,在必要的时候还可以手动修改文件特征码。 3、突破防火墙与进程隐藏。木马文件执行的时候需要与攻击端通信,必须访问网络。但不仅第三方的个人防火墙会阻拦你,现在Windows XP SP2也自带了软件防火墙。当“不可信任”的应用程序访问网络时,防火墙会报警。我的解决方法是:将网络通信部分的代码作为远程线程注入到防火墙“可信任”的进程中。这个“可信任”的进程一般是系统进程,也可以是IE。代码的注入,同时起到了进程隐藏的作用。 4、拖动并执行“大马”。这是汇编木马的核心功能,也是本文要重点举例讨论的内容。最终的监控、跟踪功能是在“大马”中实现的,它可以通过高级语言来实现,体积大小并没有什么限制。 Win32汇编基础 为了进行下面的讨论,Win32汇编是大家必须掌握的基础知识。Win32汇编生成的程序也是运行在Windows保护模式下的。我们可以通过下面几个方面去了解: 1、Win32ASM编译器 Win32ASM编译器最常用的有两种:Borland公司的Tasm5.0和Microsoft的Masm6.11及以上版本,两种编译器各有自己的优缺点,本文选用Microsoft

汇编语言入门教程

汇编语言入门教程 汇编语言是一种低级编程语言,直接与计算机硬件进行交互,对于学习计算机原理和底层开发非常重要。本文将为您介绍汇编语言的基本概念和使用方法,以及如何开始编写汇编程序。 一、汇编语言简介 汇编语言是一种以指令集为基础的机器语言,它使用助记符号来代替二进制代码,使程序的编写更加直观。汇编语言与特定的计算机体系结构紧密相关,不同的处理器有不同的汇编语言。 二、准备工作 在开始学习汇编语言之前,您需要一台支持汇编语言开发的计算机和相应的开发工具。常用的汇编语言开发工具有MASM、NASM和FASM等。您可以根据自己的需求选择合适的工具。 三、汇编指令和寄存器 1. 汇编指令 汇编语言的指令包括数据传输指令、算术逻辑指令、控制转移指令等。每个指令执行特定的操作,例如MOV指令可以将数据从一个位置传输到另一个位置。 2. 寄存器

寄存器是计算机内部一小块非常快速的内存空间,用于存储临时数据和地址。常见的寄存器有通用寄存器、状态寄存器和段寄存器等。在编写汇编程序时,您需要了解不同寄存器的作用和使用方法。 四、汇编程序的基本结构 一个典型的汇编程序由如下几个部分组成: 1. 数据段:用于存储程序所需的数据 2. 代码段:包含汇编指令,定义程序执行的步骤和过程 3. 堆栈段:用于存储程序的运行时数据和函数调用时的参数 五、汇编程序实例 以下是一个简单的汇编程序示例,实现将两个数相加并将结果存储到指定的位置: ```assembly section .data number1 db 10 number2 db 5 result db ? section .text global _start _start:

windows环境下32位汇编语言程序设计附书代码

windows环境下32位汇编语言程序设计附书 代码 汇编语言是一种底层计算机语言,用于编写与计算机硬件直接交 互的程序。在Windows环境下,可以使用32位汇编语言进行程序设计。本文将介绍一些常见的32位汇编语言程序,并附带相关的代码示例。 1.程序的基本结构: 在32位汇编语言中,程序的基本结构由三个部分组成:数据段、 代码段和堆栈段。 数据段用来声明和初始化程序中使用的全局变量和常量。例如, 下面的代码段声明了一个全局变量message,存储了一个字符串。 ``` data segment message db 'Hello, World!',0 data ends

``` 代码段包含了程序的实际执行代码。下面的代码段使用`mov`指令将message变量中的字符串存储到寄存器eax中,并使用`int 21h`来调用MS-DOS功能1来显示字符串。 ``` code segment start: mov eax, offset message mov ah, 09h int 21h mov ah, 4ch int 21h code ends ``` 堆栈段用来存储函数调用过程中的局部变量和返回地址。

2.入栈和出栈操作: 在程序中,我们经常需要使用堆栈来保存和恢复寄存器的值,以及传递函数参数和保存函数返回值。以下是一些常用的堆栈操作指令: ``` push reg ;将reg中的值压入堆栈 pop reg ;将堆栈顶部的值弹出到reg中 ``` 下面的示例演示了如何使用堆栈来保存和恢复寄存器的值: ``` code segment start: push eax ;将eax保存到堆栈 mov eax, 10 ;设置eax的值为10 pop ebx ;将堆栈顶部的值弹出到ebx

经典汇编语言教程

经典汇编语言教程 汇编语言(Assembly Language)是面向机器的程序设计语言。汇编语言是高效的低级程序设计语言,是利用计算机所有硬件特性并能直接控制硬件的语言。 Windows32位汇编语言程序设计教程 Windows环境下32位汇编语言(win32asm)是一种全新的编程语言。它使用与C++语言相同的API接口,不仅可以用来开发出大型的软件,而且是了解操作系统运行细节的最佳方式。本书从编写应用程序的角度,从“Hello World!”这个简单的例子开始到编写多线程、注册表和网络通信等复杂的程序,通过60多个实例逐渐深入Win32汇编语言的方方面面。 Windows API应用程序编程接口函数 Windows API(Windows Application Programming Interface)即:Windows应用程序编程接口;API函数是Microsoft Windows 32位平台的应用程序编程接口,所有API函数代码放在Windows系统目录下的DLL动态连接库文件中(主要是 Kernel32.dll,User32.dll,GDI32.dll,Shell32.dll...);在Windows 工作环境下执行的应用程序都可以调用Windows API函数;另外Java平台也有一套API函数。MicroSoft DOS命令大全 DOS即Disk Operating System(磁盘操作系统)是一个基于磁盘管理的操作系统。 DOS是伴随PC机出现而被开发出来的,广泛应用于早期的PC机上。MicroSoft Office VBA 教程 VBA(全称为:Visual Basic for Applications)是一种Visual Basic的一种宏语言,主要能用来扩展Windows的应用程式功能,特别是Microsoft Office软件。也可说是一种应用程式视觉化的Basic Script。1994年发行的Excel 5.0版本中,即具备了VBA

win32汇编程序设计

win32汇编程序设计 Win32汇编程序设计 Win32汇编是一种基于x86架构的汇编语言,用于开发Windows操作系统的应用程序。它的设计目标是实现高效、快速和可靠的程序,利用底层硬件资源来实现更高级别的功能。本文将介绍Win32汇编的概念、特点和应用,以及如何进行Win32汇编程序设计。 一、Win32汇编的概念和特点 Win32汇编是一种面向Windows平台的汇编语言,它是基于Intel x86架构的指令集。与高级语言相比,汇编语言更接近底层硬件,可以直接控制计算机的寄存器、内存和外设等资源。Win32汇编程序可以通过调用Windows API函数来实现各种功能,如图形界面、文件操作、网络通信等。 Win32汇编具有以下特点: 1. 直接访问硬件资源:Win32汇编允许程序员直接访问寄存器、内存和外设等底层硬件资源,从而实现更高级别的功能。这种直接访问的特性使得Win32汇编在一些对效率要求较高的应用场景中具有优势。 2. 高效、快速:由于汇编语言直接操作底层硬件,因此具有更高的执行效率和更快的运行速度。这使得Win32汇编在一些对性能要求

较高的应用中被广泛使用,如游戏开发、图像处理等。 3. 灵活性:Win32汇编语言具有很高的灵活性,可以根据具体需求进行定制化开发。程序员可以直接控制底层资源,实现特定的功能,而不受高级语言的限制。 二、Win32汇编的应用领域 Win32汇编广泛应用于Windows操作系统的应用程序开发中。以下是一些典型的应用领域: 1. 系统工具开发:Win32汇编可以用于开发各种系统工具,如磁盘清理工具、注册表编辑工具等。通过直接访问底层资源,可以实现更高级别的功能。 2. 游戏开发:由于Win32汇编具有高效、快速的特点,因此在游戏开发中被广泛应用。通过直接操作硬件资源,可以实现更复杂的游戏逻辑和更出色的性能。 3. 图像处理:Win32汇编可以用于图像处理领域,如图像压缩、图像滤波、图像识别等。通过直接操作像素数据,可以实现更高效的图像处理算法。 4. 网络通信:Win32汇编可以用于网络通信领域,如网络编程、Socket编程等。通过调用Windows API函数,可以实现各种网络功能,如建立连接、发送数据等。

Lcc-win32面向Windows编程图解教程

Lcc-win32面向Windows编程图解教程 为什么使用Lcc? 当各种版本Visual C++ Windows编程的书汗牛充栋的时候,当无论是高手还是初学者都用Visual C++ 编程的时候,干嘛要有用Lcc进行Windows编程的书? ? Lcc是自由软件,公开源代码,至少是免费的!虽然V isual C++的学生版或速成版很便宜,尤其是用美元计价且用高级程序员的收入衡量的时候。但微软的商品即便免费给你,你的感觉仍是被拴住鼻子,早晚你会把血汗钱给盖茨,劫贫济富一把。 ? 用Lcc能深入了解编程是怎么回事。Windows编程的工具太强大,他就会代替你做很多基础层面的事。而这些基础正式初学者应该熟练掌握的!想想为什么我们小学时先学加减法而不是想学使用计算器。但是如果工具太简单也不行,用小刀是无法刻出CPU的。 ? Lcc软件的作者们是一群编程的精英,包括Dennis Ritchie, C语言的发明者。他们花费了惊人的脑力写出Lcc的IDE、编译器和丰富的文档,我们若不学会用它,不是太暴殄天物了吗? 为什么使用C语言? C语言的历史很悠久,所以他的缺点被揭露、他被批判的历史也很长。可是好多编程语言出现又消失,C语言的地位仍未被撼动。而且C语言被更为广泛的应用。 正如Lcc所自带的文档《Programming with lcc-win32》所说的: 如果你想写能被长时间使用的软件,不要学当今最火的编程语言,学C语言。 C不强加你任何观点。她不是面向对象(object oriented)的,但如果你愿意,你可以用C 语言进行面向对象的程序设计。她不是函数语言(functional language),但如果你愿意,你可以用C语言进行函数语言范式程序设计。大多数LISP语言和Scheme语言(一种完全的函数语言)的解释器和编译器就是用C语言编的!你用C语言进行链接表处理也许不如用LISP语言好用,但是你是可以用C语言进行链接表处理的。C语言有所有编程语言的本质特性…… if you write software that is going to stay for some time, do not learn “the language of the day”: learn C. C doesn’t impose you any point of view. It is not object oriented, but you can do object oriented programming in C if you wish. It is not a functional language but you can do functional programming with it if you feel like. Most LISP interpreters and Scheme interpreters/compilers are written in C. Y ou can do list processing in C, surely not so easily like in lisp, but you can do it. It has all essential features of a general purpose programming language… 进入Lcc界面 当点击Windows开始菜单→程序→Lcc-win32→Lcc-win32快捷方式时,或双击C:\lcc\bin默认安装位置的wedit.exe,将会看到如下经典而简洁的界面: 历史回顾:命令行式的人机对话 为了便于阐述面向Windows编程的特点,我们回到历史中,看看类似DOS时代的命令行式的人机对话程序是怎样编出来的。 本来想展示个经典的HelloWorld程序,可是HelloWorld程序太经典,出现的太多,而且没有人机对话,有点傻! 我们编一个计算正方形面积的程序。 计算机先问人类“正方形的边长是?”,人类输入个整数,计算机给出“正方形的面积=整

Win32汇编语言简明教程

第一课基本概念 我们先假设您已知道了如何使用MASM。如果您还不知道的话,请下载 win32asm.exe ,并请仔细研读其中所附带的文档资料。好,如果您已准备就绪,我们这就开始吧! 理论: WIN32 程序运行在保护模式下的,保护模式的历史可以追溯到 80286。而今80286 已成为了历史。所以我们将只把精力集中于 80386 及后续的X86 系列CPU。Windows 把每一个 Win32 应用程序放到分开的虚拟地址空间中去运行,也就是说每一个应用程序都拥有其相互独立的 4GB 地址空间,当然这倒不是说它们都拥有 4GB 的物理地址空间,而只是说能够在 4GB 的范围内寻址。操作系统将会在应用程序运行时完成 4GB 的虚拟地址和物理内存地址间的转换。这就要求编写应用程序时必须格守 Windows 的规范,否则极易引起内存的保护模式错误。而过去的 Win16 内存模式下,所有的应用程序都运行于同一个 4GB 地址空间,它们可以彼此"看"到别的程序的内容,这极易导致一个应用程序破坏另一个应用程序甚至是操作系统的数据或代码。 和 16 位 Windows 下的把代码分成 DATA,CODE 等段的内存模式不同,WIN32 只有一种内存模式,即 FLAT 模式,意思是"平坦"的内存模式,再没有 64K 的段大小限制,所有的 WIN32 的应用程序运行在一个连续、平坦、巨大的 4GB 的空间中。这同时也意味着您无须和段寄存器打交道,您可以用任意的段寄存器寻址任意的地址空间,这对于程序员来说是非常方便的,这也使得用32位汇编语言和用C语言一样方便。在Win32下编程,有许多重要的规则需要遵守。有一条很重要的是:Windows 在内部频繁使用 ESI,EDI,EBP,EBX 寄存器,而且并不去检测这些寄存器的值是否被更改,这样当您要使用这些寄存器时必须先保存它们的值,待用完后再恢复它们,一个最显著的应用例子就是 Windows 的CallBack 函数中。 内容: 下面的程序段是一个框架,若您现在还不知道这些指令的确切意义的话,没关系,随后我就会给大家详细解释。 .386 .MODEL Flat, STDCALL .DATA ...... .DATA? ......

Win32汇编教程(基础)

汇编语言基础win32 一、引言 Win32应用程序一般使用C语言编程,但是在某些需要进行深层编程的情况下,例如Win32应用程序执行机制分析、病毒清除、加密解密等深层编程,或者对于某些速度要求较高的程序,需要使用汇编语言(甚至机器语言)直接编写Win32应用程序。Win32应用程序虽然和其他32位应用程序(例如32位保护模式DOS 程序)一样可以使用386汇编语言和保护模式编程,但是Win32应用程序的执行机制与其他32位应用程序有一定的差别,例如消息循环、动态链接等,Win32汇编语言也有其特殊的编程方式。目前国内极少看到有关Win32汇编语言的资料,市面上的汇编语言书籍一般只介绍DOS实模式汇编语言和386保护模式汇编语言,金山公司的《深入Windows编程》一书虽然介绍了使用汇编语言写Windows应用程序的方法,可惜该书只介绍了Win16汇编语言。为了使大家能对Win32汇编语言的基本编程方法有一定的了解,近日得闲,笔者编写了本教程,旨在抛砖引玉,如果本教程能够带领你走进神秘的Win32汇编语言世界,笔者心愿足矣。使用本教程,要求读者具有C语言编写Win32应用程序(Win32SDK编程)的基础。 二、进行Win32汇编语言编程的基本软件 进行Win32汇编语言编程,应该准备下列基本软件: 1、MASM 6.11以上版本的汇编器 MASM是Microsoft公司的汇编器,这是最基本的软件,必需MASM 6.11以上版本才能够汇编Win32汇编语言源程序。不过进行Win32汇编语言编程不必要全套的MASM 6.11,只要一个ML.EXE文件就可以了,Windows 95 DDK中带有MASM 6.11c的ML.EXE文 件,Windows 98 DDK中带有MASM 6.11d的ML.EXE文件,都可以使用。Turbo MASM 5.0(TASM)是Borland公司的汇编器,也可以用来汇编Win32汇编语言源程序,但是TASM的部分语法与MASM不同,用于MASM的Win32汇编语言源程序可能需要修改后才能用TASM汇编。本教程中的所有Win32汇编语言源程序都基于MASM。 2、Win32SDK 进行Win32汇编语言编程需要用到Win32SDK中的资源编译器(RC.EXE)和连接器(LINK.EXE),还需要用到Win32SDK中的引入库文件(KERNEL32.LIB、USER32.LIB、GDI32.LIB等)。如果没有Win32SDK,Platform SDK也可以,还可以安装Visual C++ 2.0以上版本的Visual C++,笔者使用的是Visual C++ 6.0。Borland C++ 4.0以上版本的Borland C++也可以使用,只是资源编译器和连接器的 文件名不同,分别是BRC.EXE(BRC32.EXE)和TLINK.EXE(TLINK32.EXE),选项也不尽相同,另外Borland C++不支持COFF格式的OBJ文件,汇编时不能使用/coff选项。 3、汇编语言编辑器 一个普通的文本编辑器,用于编辑Win32汇编语言源程序。EDIT、PWB等都可以,Visual C++等编程语言中的编辑器也可以,甚至WORD、WPS 97等可以编

win32汇编除法

win32汇编除法 摘要: 1.汇编语言简介 2.win32汇编环境介绍 3.win32汇编中的除法操作 4.除法指令的语法与使用 5.实例分析 6.总结 正文: 汇编语言是一种低级编程语言,它与计算机硬件的操作紧密相关。汇编语言通过对计算机硬件的操作进行符号化,使得程序员可以更加方便地进行编程。在win32汇编环境中,汇编语言被广泛应用于编写系统程序、驱动程序等底层应用程序。 在win32汇编中,除法操作是程序员经常需要处理的一种运算。为了实现除法操作,win32汇编提供了一系列的除法指令。这些指令的语法和使用方法各有不同,但它们的主要目的都是实现除法运算。 以下是win32汇编中除法指令的一些例子: - DIV:将两个操作数相除,商存储在寄存器中,余数存储在标志寄存器中。 - IDIV:将两个操作数相除,商和余数都存储在寄存器中。 - DIVL:将两个操作数相除,商存储在内存中,余数存储在标志寄存器

中。 - IDIVL:将两个操作数相除,商和余数都存储在内存中。 在使用除法指令时,需要注意以下几点: - 操作数必须为整数。 - 商和余数的存储位置取决于指令的格式。 - 如果有符号数进行除法运算,结果的符号位由两个操作数的符号位决定。 下面通过一个实例来分析win32汇编中的除法操作: ``` mov ax, 12345h mov bx, 1000h div bx ``` 上述代码将把12345h(即十进制的4161)除以1000h(即十进制的4096)。执行完这条指令后,ax寄存器中存储的将是商(即3),而标志寄存器中存储的将是余数(即161)。 总之,在win32汇编中,除法操作可以通过使用一系列特定的指令来实现。这些指令的语法和使用方法各有不同,但它们都可以帮助程序员实现除法运算。

win32汇编除法

win32汇编除法 1. 简介 win32汇编是一种低级编程语言,用于在Windows操作系统上编写应用程序。在win32汇编中,除法操作是非常常见的,它允许将两个数相除并得到商和余数。 本文将介绍win32汇编中的除法操作,包括如何使用除法指令、处理异常和处理特殊情况。 2. 除法指令 win32汇编提供了两个除法指令:div和idiv。 •div指令用于无符号整数的除法操作。它使用eax寄存器作为除数,并将商存储在eax中,余数存储在edx中。 •idiv指令用于有符号整数的除法操作。它使用eax寄存器作为除数,并将商存储在eax中,余数存储在edx中。 以下是一个示例程序,展示如何在win32汇编中使用除法指令: mov eax, 10 ; 设置除数 mov ebx, 3 ; 设置被除数 div ebx ; 无符号整数除法 ; 此时 eax = 3(商),edx = 1(余数) idiv ebx ; 有符号整数除法 ; 此时 eax = -3(商),edx = 1(余数) 3. 处理异常 在进行除法操作时,可能会出现一些异常情况,例如被除数为0或除数与被除 数的符号不同。为了处理这些异常,win32汇编提供了一些标志位。 •CF(Carry Flag)标志位用于指示除法操作是否溢出。如果除数为0,则CF会被设置为1。 •ZF(Zero Flag)标志位用于指示商是否为0。如果商为0,则ZF会被设置为1。 以下是一个处理除法异常的示例程序: mov eax, 10 ; 设置除数 mov ebx, 0 ; 设置被除数为0

div ebx ; 无符号整数除法 jnc success ; 如果没有溢出,跳转到成功处理的标签 ; 处理除法异常的代码 ; ... success: ; 处理除法成功的代码 ; ... 4. 处理特殊情况 除法操作还涉及一些特殊情况的处理。例如,当进行除法操作时,如果商的结 果无法放入指定的寄存器,会导致溢出。 为了处理这种情况,可以使用cwd指令将32位有符号整数转换为64位有符 号整数。然后可以使用idiv指令进行除法操作,并将商存储在dx:ax(高位在dx,低位在ax)中。 以下是一个处理特殊情况的示例程序: mov ax, 0xFFFF ; 设置除数的低16位为-1(有符号最大值) cwd ; 将16位有符号整数扩展为32位有符号整数 mov bx, 2 ; 设置被除数 idiv bx ; 有符号整数除法 ; 此时 dx:ax = -32767(商),余数存储在dx中 5. 总结 本文介绍了win32汇编中的除法操作。我们了解了除法指令的使用方法,以及如何处理除法的异常和特殊情况。 在编写Win32汇编程序时,合理地使用除法操作有助于实现复杂的数学运算 和算法。因此,熟悉除法操作是成为Win32汇编程序员的必备技能之一。 希望本文能对初学者了解win32汇编中的除法操作提供一些帮助。

win32汇编语言

win32汇编语言 Win32汇编语言是一种低级别的程序语言,用于开发应用程序和操作系统。它是一种基于 x86 架构的汇编语言,可直接访问计算机硬件。在本文中,将介绍一些常见的Win32汇编语言 的基本知识和参考内容。 首先,了解如何在Win32汇编语言中使用寄存器是非常重要的。在x86架构中,有许多寄存器可用于存储数据和执行运算。其中包括通用寄存器(如EAX、EBX、ECX、EDX)和特殊 用途寄存器(如EIP、ESP、EBP)。了解如何正确使用这些 寄存器对于编写高效和可靠的汇编代码至关重要。 其次,学习如何使用Win32 API函数是编写Win32汇编语言 程序所必需的。Win32 API是一组函数和接口,用于与Windows操作系统进行交互。通过调用这些函数,可以执行 各种任务,如创建窗口、处理消息、操作文件等。了解如何使用这些函数,可以使程序获得更多的功能和灵活性。 此外,了解如何操作内存也是编写Win32汇编语言程序所必 需的。在程序运行时,需要使用内存来存储和操作数据。了解如何分配和释放内存,以及如何使用不同的内存段(如堆栈和数据段)是非常重要的。同时,了解如何进行内存读写操作,如移动数据、复制数据等,也是编写高效程序所必需的技能。 另外,学习如何处理异常和错误也是非常重要的。在编写程序时,难免遇到各种错误和异常情况。了解如何正确处理这些错误和异常,可以使程序更加健壮和可靠。Win32 API提供了一

些处理错误和异常的函数和接口,如SetLastError和GetLastError等。 最后,了解如何进行调试和优化是编写Win32汇编语言程序 的关键。在程序开发过程中,经常需要进行调试和优化,以确保程序的正确性和性能。Win32汇编语言提供了一些调试和优化工具,如调试器和性能分析器等。了解如何使用这些工具可以帮助程序员更快地定位和解决问题,提高程序的执行效率。 综上所述,了解如何使用寄存器、Win32 API函数、内存操作、异常处理以及调试和优化工具是编写Win32汇编语言程序的 基本要点。在深入学习和实践这些知识的过程中,建议阅读一些经典的Win32汇编语言书籍和教程,如《Windows汇编编 程从入门到精通》、《编程逆向工程》等。此外,还可以参考一些在线资源和社区,如Stack Overflow、Win32 API官方文 档等。通过不断学习和实践,可以掌握Win32汇编语言编程,开发出高效和可靠的应用程序。

汇编语言入门教程

汇编语言入门教程 汇编语言是一种低级机器语言的抽象表示形式,它将计算机底层的指令表示为可读的文本形式。掌握汇编语言对于理解计算机硬件和编写高效的程序非常重要。本教程将带您从零开始学习汇编语言的基础知识和编程技巧。 第一部分:介绍和准备工作 1.1什么是汇编语言? 1.2为什么要学习汇编语言? 1.3汇编语言的基本特点和用途 1.4开发环境的准备 第二部分:汇编语言基础 2.1数据表示和计算机内存 2.2寄存器和指令 2.3内存寻址方式 2.4常用汇编指令 2.5标志寄存器和条件分支指令 第三部分:汇编语言编程技巧 3.1数据的传递和处理 3.2循环和分支结构

3.3子程序的调用和返回 3.4输入和输出操作 3.5中断处理和异常控制 第四部分:实例和应用 4.1计算机硬件的控制 4.2内存和外设的读写操作 4.3实践项目和应用案例 第五部分:调试和优化 5.1调试汇编程序 5.2性能优化和代码压缩技巧 5.3代码的移植和扩展 在学习汇编语言时,您需要了解计算机的基本结构和组成部分,包括中央处理器(CPU)、寄存器、内存等。您还需要安装一款支持汇编语言的集成开发环境(IDE),并了解如何进行编译、调试和执行程序。 在学习汇编语言的基础知识时,您将学习如何表示和处理不同类型的数据,例如整数、浮点数和字符串。您还将学习如何使用寄存器进行数据传输和计算,以及如何使用不同的寻址方式访问内存中的数据。 在学习汇编语言的编程技巧时,您将学习如何使用循环和分支结构进行条件判断和控制流程。您还将学习如何编写子程序进行模块化的程序设计,并学习如何进行输入和输出操作以及异常处理。

汇编语言入门教程

汇编语言入门教程 在学习汇编语言之前,我们先了解一些基本概念。汇编语言是一种低级语言,它与计算机硬件直接相关。它使用特定的指令集来操作计算机的寄存器、存储器和其他设备。汇编语言的编程者必须具备对计算机硬件的深入了解,包括CPU的结构和指令集,以及内存的组织和管理。 在编写汇编语言程序时,我们首先需要选择合适的汇编器来将程序转换成机器码。汇编器是一种将汇编语言转换为机器码的工具。常用的汇编器有MASM、NASM和GNU汇编器。在选择汇编器之前,我们需要了解所用计算机的硬件架构和操作系统的要求。 下面我们来看一个简单的汇编语言程序示例: ```assembly section .data message db 'Hello, World!', 0 section .text global _start _start: ; 输出字符串 mov eax, 4 mov ebx, 1 mov ecx, message mov edx, 13

int 0x80 ; 退出程序 mov eax, 1 xor ebx, ebx int 0x80 ``` 在上面的示例中,我们定义了一个字符串变量message,并在程序中输出了该字符串。首先,我们将字符串的地址保存在ecx寄存器中,然后使用系统调用将字符串输出到标准输出。 接下来,我们使用了另一个系统调用来退出程序。我们将1保存在eax寄存器中,表示退出程序的系统调用编号。通过将ebx寄存器的值设置为0,我们告诉操作系统程序退出时不返回任何错误代码。 这只是一个简单的汇编语言程序示例,但它涵盖了汇编语言程序的基本结构和语法。在接下来的教程中,我们将逐步学习如何编写更复杂的汇编语言程序,并介绍汇编语言的各种特性和技巧。

菜鸟从零开始玩汇编

菜鸟从零开始玩汇编.txt爱情就像脚上的鞋,只有失去的时候才知道赤脚走路是什么滋味骗人有风险,说慌要谨慎。不要爱上年纪小的男人,他会把你当成爱情学校,一旦学徒圆满,便会义无反顾地离开你。总是有人问我:我是菜鸟,想学编程,应该学什么啊? 我总是和他说:哎呀,你自己学什么自己按需来啊,最先学就学C语言吧。 呵呵,其实学编程没有什么困难的,今天我就教你入门一个语言——汇编 现在网上汇编的教程也挺难找的 希望我写的这个可以给大家分享一下经验 祝愿大家早日成功,到时候别忘了我啊:) 第一步——安装 1. 去下载一个masm的系列来当作我们的汇编器,说实话,这东西真的让汇编简单多了,我们由于是win32下的汇编,所以我们就不用费那么大的劲去学什么I/O系统了,好我已经下载好了,工具自己去搜索下载,首先我们安装我的是masm8.0的版本。不过先在的最新版本是8.2的,喜欢的可以去下载那个 我们选择要安装的地方,我喜欢选择D盘,当然选择哪个盘是你自己的想法。 2. 运行安装程序 如图1 我们选择D,然后按install masm32 然后会跳出一个对话框 如图2 我们按确定。 然后等待一段时间。(我等待了43秒) 3. 然后会跳出一个命令提示符 如图3 我们按4来进行安装,然后继续等待他来安装 如果没什么意外的话,应该很快的,我用了10多秒就安装完了 然后 如图4 我们按确定 这样我们进行win32的汇编器已经安装了,那么就开始下一步吧 第二步——架设环境 什么编程几乎都需要环境。比如asp就需要IIS的环境来实现,vc++也需要设置环境,java,jsp,没有不需要设置环境的 汇编也不例外,那么如何架设环境呢? 1. 查看下列地方 由于我是windows2003 server的,所以我就在我的电脑——高级——环境变量里面设置 如图5 由于我先前已经装了Microsoft Visual Studio系列软件,所以我已经有了incluede,lib,path这3个变量,如果没有的你新建incluede,lib,path这三个变量,然后按编辑,里面的内容是你装masm32的本地路径,我们安装在D盘下面,所以我们就要设置

汇编语言入门教程.doc

汇编语言入门教程 2007-04-29 22:04 对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩DEBUG ,有时CRACK 出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样) 。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上 ( CMP LOOP MOV JNZ ,, ) 。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩(用WINZIP 、WINRAR , 依次压迫,嘿嘿! )教程。大言不惭的说,看通本文,你完全可以“不经意”间在前辈或是后生卖弄一下DEBUG ,很有成就感的,试试看!那么这个接下来呢?Here we go !(阅读时看不懂不要紧,下文必有分解) 因为汇编是通过CPU 和内存跟硬件对话的,所以我们不得不先了解一下CPU 和内存:(关于数的进制问题在此不提) CPU是可以执行电脑所有算术/逻辑运算与基本I/O控制功能的一块芯片。一种汇编语 言只能用于特定的CPU。也就是说,不同的CPU其汇编语言的指令语法亦不相同。个人电脑由1981年推出至今,其CPU发展过程为:8086^ 80286宀80386宀80486^ PENTIUM t”,还有AMD、CYRIX等旁支。后面兼容前面CPU的功能,只不过多了些指令(如 多能奔腾的MMX指令集)、增大了寄存器(如386的32位EAX )、增多了寄存器(如486 的FS)。为确保汇编程序可以适用于各种机型,所以推荐使用8086汇编语言,其兼容性最佳。本文所提均为8086汇编语言。寄存器(Register)是CPU内部的元件,所以在寄存器之间的数据传送非常快。用途: 1.可将寄存器内的数据执行算术及逻辑运算。 2.存于寄存器 内的地址可用来指向内存的某个位置,即寻址。 3.可以用来读写数据到电脑的周边设备。8086 有8个8位数据寄存器,这些8位寄存器可分别组成16位寄存器:AH &AL = AX :累 加寄存器,常用于运算;EH & BL = BX :基址寄存器,常用于地址索引;CH &CL = CX:计数寄存器,常用于计数;DH &DL = DX :数据寄存器,常用于数据传递。为了 运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:CS( Code Segment):代码段寄存器;DS( Data Segment):数据段寄存器;SS( Stack Segment): 堆栈段寄存器;ES( Extra Segment):附加段寄存器。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS 来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于 64K 的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS 所指的64K 内,这就是COM 文件不得大于64K 的原因。8086以内存做为战场,用寄存器做为军事基地,以加速工作。除了前面所提的寄存器外,还有一些特殊功能的寄存器:IP( Intruction Pointer):指令指针寄存器,与CS配合使用,可跟踪程序的执行过程;SP (Stack Pointer): 堆栈指针,与SS配合使用,可指向目前的堆栈位置。BP ( Base Pointer):基址指针寄存器, 可用作SS 的一个相对基址位置;SI( Source Index) 源变址寄存器可用来存放相对于DS 段之源变址指针;DI(Destination Index) 目的变址寄存器,可用来存放相对于ES 段之目的变址指针。还有一个标志寄存器FR( Flag Register) ,有九个有意义的标志,将在下文用到时详细说明。 内存是电脑运作中的关键部分,也是电脑在工作中储存信息的地方。内存组织有许多可存放 数值的储存位置,叫“地址” 。8086地址总线有20位,所以CPU 拥有达1M 的寻址空间,这也是DOS 的有效控制范围,而8086能做的运算仅限于处理16位数据,即只有0到64K,所以,必

汇编教程

单击菜单文件à新建文件或按快捷键Ctrl+N,在代码编辑窗口中键入如下的代码:(注意大小写敏感) 完成后我把代码保存为F:\backupDoc\test.asm,然后再单击菜单构建。 如果大家还记得的话,就知道这是编译、连接、运行一次搞定的选项,当编译 路径没有配置错误,程序即会进行编译、连接和运行。 至于汇编代码我就不解析了,也不是本教程的范围。如果编译期间发生了错误,则可以在输出窗口中查看错误提示,一般第一次的错误都是没有设置好Masm32的路径。如果没错的话RadAsm会显示整个编译和连接的过程,如上面的程序就输出如下信息: F:\Asm\masm32\Bin\ML.EXE /c /coff /Cp /nologo /I"F:\Asm\masm32\Include" "F:\backupDoc\test.asm" Assembling: F:\backupDoc\test.asm F:\Asm\masm32\Bin\LINK.EXE /SUBSYSTEM:WINDOWS /RELEASE /VERSION:4.0 /LIBPATH:"F:\Asm\masm32\Lib" "F:\backupDoc\test.obj" Microsoft (R) Incremental Linker Version 5.12.8078 Copyright (C) Microsoft Corp 1992-1998. All rights reserved. Executing: "F:\backupDoc\test.exe" Make finished. Total compile time 1693 ms 好了,我们现在打开RadAsm,单击菜单文件——新建工程,在弹出的对话框中设置好工程名和工程的类型,如下图所示:

相关文档
最新文档