Iczelion的Win32汇编教程031

合集下载

WIN32汇编

WIN32汇编

Windows版本我们也可以建一个Windows版的Hello World!程序。

将下面的代码粘贴到文本编辑器中并保存为“Hellow.asm”。

.386.model flat, stdcalloption casemap :noneinclude \masm32\include\windows.incinclude \masm32\include\kernel32.incinclude \masm32\include\user32.incincludelib \masm32\lib\kernel32.libincludelib \masm32\lib\user32.lib.dataHelloWorld db "Hello World!", 0.codestart:invoke MessageBox, NULL, addr HelloWorld, addr HelloWorld, MB_OKinvoke ExitProcess, 0end start现在,再次打开命令行并进入到保存“Hellow.asm”的目录里。

输入"\masm32\bin\ml /c /Zd /coff hellow.asm"。

然后再输入“\masm32\bin\Link /SUBSYSTEM:WINDOWS hellow.obj”,注意参数中的subsystem选项又原来的CONSOLE替换成了WINDOWS。

这个程序将会弹出一个对话框来显示“Hello World!”。

Windows版本和控制台版本仅仅有3行代码不同。

首先两处更改的是为了我们现在能使用MessageBox函数来替换之前的StdOut,必须加入user32的包含文件和库文件。

第三个改变就是使用MessageBox函数来替换StdOut函数。

完了,就这些。

ADDR vs OFFSET在我们的Hello World!例子中,我们使用了‘addr’来获取“Hello World”字符串的地址。

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汇编教程

Win32汇编教程

Win32汇编教程之一Win32汇编的环境和基础--------------------------------------------------------------------------------1.32位环境简介在Dos下编汇编程序,我们可以管理系统的所有资源,我们可以改动系统中所有的内存,如自己改动内存控制块来分配内存,自己修改中断向量表来截获中断等,对其他操作也是如此,如我们对键盘端口直接操作就可以把键盘屏蔽掉,可以这样来描述Dos系统:系统只有一个特权级别,在编程上讲,任何程序和操作系统都是同级的,所以在Dos下,一个编得不好的程序会影响其他所有的程序,如一个程序把键盘口中断关掉了,所有程序就都不能从键盘获得键入的数据,直到任何一个程序重新打开键盘为止,一个程序陷入死循环,也没有其他程序可以把它终止掉。

Dos下的编程思路是“单任务”的,你只要认为你的程序会按照你的流程一步步的执行下去,不必考虑先后问题(当然程序可能会被中断打断,但你可以认为它们会把环境恢复,如果中断程序没有把环境恢复,那是他们的错)。

在内存管理方式上,Dos汇编和Win32汇编也有很多的不同:Dos工作在实模式下,我们可以寻址1M的内存,寻址时通过段寄存器来制定段的初始地址,每个段的大小为64K,超过1M的部分,就只能把他作为XMS使用,也就是说,只能用作数据存放使用而无法在其中执行程序。

而Windows 在保护模式下执行,这里所有的资源对应用程序来说都是被“保护”的:程序在执行中有级别之分,只有操作系统工作在最高级--0级中,所有应用程序都工作在3级中(Ring3),在Ring3中,你无法直接访问IO端口,无法访问其他程序运行的内存,连向程序自己的代码段写入数据都是非法的,会在Windows的屏幕上冒出一个熟悉的蓝屏幕来。

只有对Ring0的程序来说,系统才是全开放的。

在内存方面,Windows使用了处理器的分页机制,使得对应用程序来说,所有的内存都是“平坦”的,你不必用一个段寄存器去指定段的地址,因为在保护模式下,段寄存器的含义是不同的(可以参见80386手册方面的书籍),你可以直接指定一个32位的地址来寻址4GB的内存。

WIN32汇编程序PPT课件

WIN32汇编程序PPT课件

例4
count darray
.model small .386
;采用32位指令
.stack
.data
equ 10
dd 20,4500h,3f40h,-1,7f000080h
dd 81000000h,0fffffff1h
dd -45000011,12345678
dd 87654321
.code
.startup
条件转移
转移范围可达到32位全偏移
Jcc label
;cc为真,转移到label指定的转段移内范偏围移仍地为址处短转移
JECXZ label ;ECX=0,转移到label指定的段内偏移地址处
LOOP/LOOPZ/LOOPNZ label ;循环指令,32位段采用ECX作为计数器
例1
;将AX的每一位依次重复一次 ;所得的32位结果保存于EAX中 mov ecx,16 mov bx,ax next:shr ax,1 rcr edx,1 shr bx,1 rcr edx,1 loop next mov eax,edx
;平衡堆栈
通用寄存器全部进出栈
PUSHA
;顺序将AX/CX/DX/BX/SP/BP/SI/DI压入堆栈
POPA
;顺序从堆栈弹出 DI/SI/BP/SP/BX/DX/CX/AX (与PUSHA相反) ;其中应进入SP的值被舍弃,并不进入SP,SP 通过增加16来恢复
符号扩展和零位扩展
MOVSX r16,r8/m8 ;把r8/m8符号扩展并传送至r16 MOVSX r32,r8/m8/r16/m16 ;把r8/m8/r16/m16符号扩展并传送至r32 MOVZX r16,r8/m8
三、32位指令的程序设计

Win32汇编教程3-对话框和资源文件的使用

Win32汇编教程3-对话框和资源文件的使用
Win32汇编教程3-对话框和资源文件的使用
| 首页 >> 编程详解 >> 罗云彬的Win32汇编教程 | Win32ASM 论坛 | 联系站长 |
Win32汇编教程3-对话框和资源文件的使用
作者:罗云彬·发布日期:2000-6-1·阅读次数:7178
【在这里下载本文的源代码】
BEGIN event, idvalue, [type] [options]
. . .
END
等等,具体的定义和参数可以参考 Masm32v5 中的 Rc.hlp 帮助文件。(可以在编程工具中下载),我们可以用资源编辑器来所见即所得地编辑资源,也可以在文本编辑器中用上面这些语句自己定义资源。
位图定义: nameID BITMAP [load-mem] filename
光标定义: nameID CURSOR [load-mem] filename
图标定义: nameID ICON [load-mem] filename
加速键定义:
acctablename ACCELERATORS [optional-statements]
; Website:
; LuoYunBin's Win32 ASM page (罗云彬的编程乐园)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

第三章 Win32汇编语言汇编语言程序设计基础指令系统PPT课件

第三章 Win32汇编语言汇编语言程序设计基础指令系统PPT课件

16
LEA 与 OFFSET
buffer db 100 dup(0)
;把字节变量buffer的EA传送给EBX
lea ebx, buffer

mov ebx, offset buffer √
buffer db 100 dup(0) lea ebx, [buffer+50] √ mov ebx, offset [buffer+50] ;X
2020/11/17
10
MOVZX / MOVSX
将源操作数的内容拷贝到目 的操作数中
MOVZX(move with zero-extend) 将该值零扩展至16位或32位
MOVSX(move with sign-extend) 将该值符号扩展至16位或32 位
目的操作数必须是寄存器
例:MOVSX EAX,CL MOVSX EDX,[EDI]
IA-32CPU指令系统包括:
① 通用指令 ② 浮点运算指令 ③ SIMD指令 ④ MMX指令(多媒体扩展指令集 ) ⑤ SSE/SSE2/SSE3指令(单指令多数据流扩展 ) ⑥ 系统指令 ⑦ 64位模式的指令
2020/11/17
3
通用指令集合
① 数据传送类指令 ② 算术运算类指令 ③ 位操作类指令 ④ 串操作类指令 ⑤ 控制转移类指令 ⑥ 处理机控制类指令 ⑦ 其他类
注意:不是获取存储器单元的内容
2020/11/17
15Βιβλιοθήκη 有效地址传送指令LEA将存储器操作数的有效地址传送至指定的 寄存器中。
在实模式下,使用16位寄存器 在保护模式下,使用32位寄存器
该指令通常用来对指针或变址寄存器EBX、 EDI或ESI等置初值之用。

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

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

windows环境下32位汇编语言程序设计附书代码汇编语言是一种底层计算机语言,用于编写与计算机硬件直接交互的程序。

在Windows环境下,可以使用32位汇编语言进行程序设计。

本文将介绍一些常见的32位汇编语言程序,并附带相关的代码示例。

1.程序的基本结构:在32位汇编语言中,程序的基本结构由三个部分组成:数据段、代码段和堆栈段。

数据段用来声明和初始化程序中使用的全局变量和常量。

例如,下面的代码段声明了一个全局变量message,存储了一个字符串。

```data segmentmessage db 'Hello, World!',0data ends```代码段包含了程序的实际执行代码。

下面的代码段使用`mov`指令将message变量中的字符串存储到寄存器eax中,并使用`int 21h`来调用MS-DOS功能1来显示字符串。

```code segmentstart:mov eax, offset messagemov ah, 09hint 21hmov ah, 4chint 21hcode ends```堆栈段用来存储函数调用过程中的局部变量和返回地址。

2.入栈和出栈操作:在程序中,我们经常需要使用堆栈来保存和恢复寄存器的值,以及传递函数参数和保存函数返回值。

以下是一些常用的堆栈操作指令: ```push reg ;将reg中的值压入堆栈pop reg ;将堆栈顶部的值弹出到reg中```下面的示例演示了如何使用堆栈来保存和恢复寄存器的值:```code segmentstart:push eax ;将eax保存到堆栈mov eax, 10 ;设置eax的值为10pop ebx ;将堆栈顶部的值弹出到ebxadd eax, ebx ;将eax和ebx相加int 3 ;调试中断,用于程序的暂停mov ah, 4chint 21hcode ends```3.条件判断和跳转指令:汇编语言中的条件判断和跳转指令用于根据条件的成立与否来改变程序的执行流程。

win32汇编程序设计

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汇编可以用于图像处理领域,如图像压缩、图像滤波、图像识别等。

win32编译

win32编译

win32编译
Win32编译主要涉及使用Windows平台下的编译器将源代码编译成可执
行文件的过程。

以下是具体的步骤:
1. 安装编译器:你需要一个Windows平台下的编译器,比如Microsoft Visual Studio。

编译器将源代码编译成目标代码。

2. 准备源代码:你需要有Win32的源代码。

这通常涉及编写或获取一个Win32应用程序的源代码。

3. 编译源代码:打开你的编译器,然后使用编译器来编译你的源代码。

如果你使用的是Microsoft Visual Studio,那么可以通过直接打开项目或解决
方案文件(通常是.sln或.vcxproj文件)来进行编译。

4. 链接目标代码:编译过程会产生目标代码,但这些代码仍然不能直接运行。

你需要使用链接器将目标代码链接成一个可执行文件。

5. 测试和调试:最后,你需要测试和调试你的应用程序以确保其正常工作。

以上步骤仅适用于一般情况,具体的步骤可能会因源代码的复杂性、编译器的版本和设置以及特定的编译需求而有所不同。

如果你在编译过程中遇到问题,可以提供更多信息,我会尽力提供更具体的帮助。

Win32汇编语言简明教程

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 函数中。

win32汇编系列(一)

win32汇编系列(一)

win32汇编系列(⼀)进程如何使⽤内存?毫⽆疑问,所有进程(执⾏的程序)都必须占⽤⼀定数量的内存,它或是⽤来存放从磁盘载⼊的程序代码,或是存放取⾃⽤户输⼊的数据等等。

不过进程对这些内存的管理⽅式因内存⽤途不⼀⽽不尽相同,有些内存是事先静态分配和统⼀回收的,⽽有些却是按需要动态分配和回收的。

对任何⼀个普通进程来讲,它都会涉及到5种不同的数据段。

稍有编程知识的朋友都能想到这⼏个数据段中包含有“程序代码段”、“程序数据段”、“程序堆栈段”等。

不错,这⼏种数据段都在其中,但除了以上⼏种数据段之外,进程还另外包含两种数据段。

下⾯我们来简单归纳⼀下进程对应的内存空间中所包含的5种不同的数据区。

代码段:代码段是⽤来存放可执⾏⽂件的操作指令,也就是说是它是可执⾏程序在内存中的镜像。

代码段需要防⽌在运⾏时被⾮法修改,所以只准许读取操作,⽽不允许写⼊(修改)操作——它是不可写的。

数据段:数据段⽤来存放可执⾏⽂件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量。

BSS段:BSS段包含了程序中未初始化的全局变量,在内存中 bss段全部置零。

堆(heap):堆是⽤于存放进程运⾏中被动态分配的内存段,它的⼤⼩并不固定,可动态扩张或缩减。

当进程调⽤malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利⽤free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)栈:栈是⽤户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。

除此以外,在函数被调⽤时,其参数也会被压⼊发起调⽤的进程栈中,并且待到调⽤结束后,函数的返回值也会被存放回栈中。

由于栈的先进先出特点,所以栈特别⽅便⽤来保存/恢复调⽤现场。

从这个意义上讲,我们可以把堆栈看成⼀个寄存、交换临时数据的内存区。

进程如何组织这些区域?上述⼏种内存区域中数据段、BSS和堆通常是被连续存储的——内存位置上是连续的,⽽代码段和栈往往会被独⽴存放。

Iczelion的Win32汇编教程032

Iczelion的Win32汇编教程032

.elseif uMsg==WM_COMMAND
.if lParam==0 ; 这条消息是由菜单产生的
mov eax,wParam
.if ax==IDM_CASCADE
.....
.elseif ax==IDM_TILEVERT
lpMsg:DWORD
第一个参数是客户窗口的句柄.对此你应该不会觉得惊讶.因为客户窗口是所有MDI子窗口的父亲. 第二个参数是你通过调用GetMessage获得的MSG框架的地址. 我们的想法是传递MSG结构给客户窗口,这样客户窗口可以检测在MSG结构中所包含的MDI相关的按键是不是按下去了.假如是的话, 客户窗口处理这个信息,然后返回一个非零值,否则返回一个假值..
第二个不同是你必须在你的框架窗口的消息循环中调用 TranslateMDISysAccel .假如你希望Windows为你处理MDI相关的加速键,比如Ctrl+F4,Ctrl+Tab,那么这是必须的.它具有下列语法:
TranslateMDISysAccel proc hwndClient:DWORD,
假如创建成功的话, SendMessage 将会返回新创建的MDI子窗口的句柄. 你并不需要保存这个句柄. 如果你需要的话, 你可以通过其它的方法来获得它. MDICREATESTRUCT有如下定义.
MDICREATESTRUCT STRUCT
szClass DWORD ?
szTitle DWORD ?
框架窗口
|
客户窗口
|
--------------------------------------------------------------------------------

Windows环境下32位汇编语言程序设计

Windows环境下32位汇编语言程序设计

Windows环境下32位汇编语言程序设计在Windows环境下,32位汇编语言程序设计在计算机科学领域中,汇编语言是一种低级别的编程语言,用于将指令直接转化为机器指令。

在Windows操作系统环境下,汇编语言的应用广泛而深入。

本文将介绍在Windows环境下,如何进行32位汇编语言程序设计。

一、汇编语言基础知识在开始学习汇编语言之前,我们需要了解一些基本的概念和知识。

首先,汇编语言是由一系列的汇编指令组成,每条汇编指令都对应着一条机器指令。

汇编指令由操作码和操作数组成,操作码指示需要进行的操作,而操作数则用于指定操作的对象。

在Windows环境下,32位汇编语言使用的是Intel x86架构,它包括了一系列的寄存器、标志位和指令集。

寄存器是用来存储数据和执行操作的一种硬件组件,其中包括通用寄存器、段寄存器和控制寄存器等。

标志位用于记录计算机处理器的状态信息,如进位、溢出、零等。

指令集则定义了可执行的操作,如加载数据、运算、跳转等。

二、编写第一个汇编程序在编写第一个汇编程序之前,我们需要准备一些工具。

首先,我们需要安装一个汇编器,如MASM(Microsoft Macro Assembler)。

其次,我们需要一个文本编辑器,如Notepad++。

接下来,就可以开始编写第一个汇编程序了。

假设我们要编写一个简单的程序,实现将两个数字相加并输出结果的功能。

首先,我们需要定义一个数据段,用于存储要操作的数据。

然后,我们需要定义一个代码段,用于编写实际的汇编指令。

以下是一个简单的示例程序:```assembly.datanum1 dw 5num2 dw 10res dw ?.codemov ax, num1 ; 将num1加载到寄存器axadd ax, num2 ; 将num2加到ax中mov res, ax ; 将结果保存到res中; 输出结果mov ah, 09h ; 设置打印字符串功能mov dx, offset res ; 将结果的内存地址加载到寄存器dxint 21h ; 调用中断21h,进行字符串打印; 结束程序mov ah, 4Ch ; 设置程序结束功能int 21h ; 调用中断21h,结束程序```以上汇编程序的功能是将num1和num2的值相加并将结果存储到res中,然后通过调用中断21h来输出结果,并最终结束程序运行。

Win32汇编教程(基础)

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调试API(3)

汇编教程Win32调试API(3)

在本章中,我们将继续探讨win32调试api。

特别地,我们将学习如何去跟踪被调试程序.理论:如果你以前使用过调试器,那么你应对跟踪比较熟悉。

当"跟踪"一个程序时,程序在每执行一条指令后将会停止,这使你有机会去检查寄存器/内存中的值。

这种单步运行的官方定义为跟踪(tracing)。

单步运行的特色是由CPU本身提供的。

标志寄存器的第8位称为陷阱标志trap flag。

如果该位设置,则CPU运行于单步模式。

CPU将在每条指令后产生一个debug异常。

当deb ug 异常产生后,陷阱标志自动清除。

利用win32调试api,我们也可以单步运行被调试程序。

方法如下:调用GetThreadContext, 指定 ContextFlags为CONTEXT_CONTROL,来获得标志寄存器的值设置CONTEXT结构成员标志寄存器regFlag中的陷阱标志位调用 SetThreadContext等待调式事件。

被调试程序将按单步模式执行,在每执行一条指令后,我们将得到调试事件,u.Exception.pExceptionRecord.ExceptionCode值为EXCEPTION_SINGLE_STEP如果要跟踪下一条指令,需要再次设置陷阱标志位。

例:.386.model flat,stdcalloption casemap:noneinclude \masm32\include\windows.incinclude \masm32\include\kernel32.incinclude \masm32\include\comdlg32.incinclude \masm32\include\user32.incincludelib \masm32\lib\kernel32.libincludelib \masm32\lib\comdlg32.libincludelib \masm32\lib\user32.lib.dataAppName db "Win32 Debug Example no.4",0ofn OPENFILENAME <>FilterString db "Executable Files",0,"*.exe",0db "All Files",0,"*.*",0,0ExitProc db "The debuggee exits",0Dh,0Ahdb "Total Instructions executed : %lu",0TotalInstruction dd 0.data?buffer db 512 dup(?)startinfo STARTUPINFO <>pi PROCESS_INFORMATION <>DBEvent DEBUG_EVENT <>context CONTEXT <>.codestart:mov ofn.lStructSize,SIZEOF ofnmov ofn.lpstrFilter, OFFSET FilterStringmov ofn.lpstrFile, OFFSET buffermov ofn.nMaxFile,512mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_E XPLORER or OFN_HIDEREADONLYinvoke GetOpenFileName, ADDR ofn.if eax==TRUEinvoke GetStartupInfo,addr startinfoinvoke CreateProcess, addr buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+ DEBU G_ONLY_THIS_PROCESS, NULL, NULL, addr startinfo, addr pi.while TRUEinvoke WaitForDebugEvent, addr DBEvent, INFINITE.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENTinvoke wsprintf, addr buffer, addr ExitProc, TotalInstructioninvoke MessageBox, 0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION.break.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT .if DBEvent.u.Exception. pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINTmov context.ContextFlags, CONTEXT_CONTROLinvoke GetThreadContext, pi.hThread, addr contextor context.regFlag,100hinvoke SetThreadContext,pi.hThread, addr contextinvoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINU E.continue.elseif DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_ST EPinc TotalInstructioninvoke GetThreadContext,pi.hThread,addr context or context.regFlag,100hinvoke SetThreadContext,pi.hThread, addr contextinvoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,DBG_CONTINUE .continue.endif.endifinvoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_EXCEPTI ON_NOT_HANDLED.endw.endifinvoke CloseHandle,pi.hProcessinvoke CloseHandle,pi.hThreadinvoke ExitProcess, 0end start分析:该程序先显示一个打开文件对话框,当用户选择了一个可执行文件,它将单步执行该程序,并记录执行的指令数,直到被调试程序退出运行。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
state 该成员变量包含的标志位反应了项目的状态。状态的改变可能是由用户的操作引起的或是程序改变的。这些状态包括:是否有焦点/高亮度显示/被选中(由于被剪切)/被选中等。另外还包括,以1为基数的索引用来代表是否处使用重叠/状态图标。
stateMask 由于上面的成员变量包含状态标志位、重叠的位图索引号、和状态位图的索引号,我们需要告诉WINDOWS我们到底需要设定或查询那一个值。该成员变量就是用来做这项工作的。
fmt 指定了项目/子项目的对齐方式。可能的值有:
LVCFMT_CENTER = 文本居中
LVCFMT_LEFT = 文本左对齐
LVCFMT_RIGHT = 文本右对齐
lx lx 是列的宽度(以像素点为单位)。以后您可以发送消息LVM_SETCOLUMNWIDTH来改变列的宽度。
iIndent dd ?
LV_ITEM ENDS
Field name Meanings
imask 一组标志位标明该结构体中那些成员变量中的值有效。它的意义和上面我们提到的LV_COLUMN型结构体中向对应的成员变量基本相同。更详细的信息,可以查询WIN32 API 手册。
iItem 该结构体代表的项目的索引号。索引号是从0开始编号的。该值和表单的“行”类似。
lParam1 和 lParam2 是 LV_ITEM型的结构体中的成员变量lParam的值。
lParamSort 是发送LVM_SORTITEMS消息时参数wParam中的值
当列表视图控件接收到LVM_SORTITEMS消息时,当需要比较项目时它会调用在lParam中指定的比较函数。比较函数将决定那一个项目排在前面。方法很简单:如果函数返回一个负值,由(lParam代表的)第一个项目排在前,如果返回正值,第二个项目排在前。如果相等,必须返回0 。
加入列要通过向列表控件发送LVM_INSERTCOLUMN消息来实现。
LVM_INSERTCOLUMN
wParam = iCol
lParam =指向LV_COLUMN型结构体变量的指针
iCol 列数,从0开始编号。
LV_COLUMN 包含了将插入的列的信息。它的定义如下:
LV_COLUMN STRUCT
创建和初始化用在列表控件中显示项目的图象列表(如果存在)。
向列表控件中插入列,如果显示的方式是报告方式这一步是必须的。
向控件中插入项目和自项目。
列:
在报告方式中,有不止一个列。您可以把放入到列表控件中的数据看作是一张表单:这时数据是按行列排列的。在控件中至少有一列。在其它的显示方式中则无所谓,因为这些显示方式有仅有一列。
imask dd ?
fmt dd ?
lx dd ?
pszText dd ?
cchTextMax dd ?
iSubItem dd ?
iImage dd ?
iOrder dd ?
LV_COLUMN ENDS
Field name Meanings
lParam 用户定义的值,当您给项目排序时使用。当您告诉列表视图对项目排序时,列表视图将成对地比较项目。 它将会把两个项目的lParam的值传给您,这样您就可以进行比较先列出那一个了。如果您现在还不太明白的话,没有系,我们稍后还要讲关于排序的问题。
现在让我们来总结想列表控件中插入项目/子项目的步骤:
pszText 当我们想设定项目的属性时,它包含项目名称的ASCII码的字符串的地址。当查询项目的属性时,该成员变量将用来接收查询返回的项目的名称。
cchTextMax 仅当您用来查询项目的属性时才需要使用该值,这时它包含上一个成员变量的大小。
iImage 图标在列表视图中的图象链表中的索引号。
上面的代码段显示了该过程。当发送LVM_INSERTCOLUMN消息时,他指定了列的标题条文本和它的宽度。
项目和子项目
项目是列表视图中主要的内容。除报告方式显示的外,在列表视图您只能看到项目。子项目是项目的详细信息。一个项目可能有不止一个相关的子项目。举个例子,譬如项目是文件名,那其相关的子项目可能有文件属性、大小、创建日期等。在报告方式的视图中,最左边一列是项目,其它列是子项目。从数据库记录的角度看,项目类似主键,子项目类似记录。
iImage and iOrder 为了和IE3.0以上版本兼容。目前我没有这方面的资料。
在列表视图控件创建后,您必须至少向其中插入一列。当然如果不打算使用报告方式显示,那倒是没有必要插入列。为了插入列,您需要定义一个LV_COLUMN型的结构体变量,给其成员变量赋上正确的值,指定列号,然后向列表视图控件发送LVM_INSERTCOLUMN消息并把该结构体变量的值传过去。
imask 一组标志位,它指示了该结构体中的那些成员变量是有效的。该结构体中的成员变量并不是同时有效的。在某些时候,可能只有某些成员变量是有效的。结构体可以用来输入和输出。这样让WINDOWS知道那些成员变量是有效的是非常重要的。可能的标志有:
LVCF_FMT = fmt有效
LVCF_SUBITEM = iSubItem有效
cchTextMax cchTextMax 以字节计的上面一个成员变量指向的缓冲区的小。该成员变量只在您查询列的属性时使用。如果是设定列的属性,那该变量将被忽略。
iSubItem 指定和该列相连的子项目的索引号。该成员变量的值用来标识和列相连系的子项目。该列的使用最好地说明了如何把列号和子项目相连。要查询列的属性时可以发送LVM_GETCOLUMN消息,并在成员变量imask中指定LVCF_SUBITEM标志,列表控件将在iSubItem中返回插入时设定的iSubItem值。为了使用该办法,您需要在该成员变量中放入正确的值。
LOCAL lvc:LV_COLUMN
mov lvc.imask,LVCF_TEXT+LVCF_WIDTH
mov lvc.pszText,offset Heading1
mov lvc.lx,150
invoke SendMessage,hList, LVM_INSERTCOLUMN,0,addr lvc
在列表视图种有四种方法来显示数据:大图标,小图标,列表和报告方式。这些方法和在资源管理器种选择View->Large Icons,Small Icons , List 和 Details 相对应。各种不同的显示方式只是显示了不同的外观而已。譬如,您可能有许多的数据,只是并不想全部显示。报告方式提供的消息最完全,其它的方式则要少得多。在刚创建一个列表视图时您可以选择一种初始显示方法,随后您可以调用SetWinodwLong函数并设置GWL_STYLE标志位来改变显示方式
至少您的列表视图需要一些项目:子项目是可选的。如果您想要给用户提供更多的信息,可以把子项目和项目相连,然后放到列表视图中以报告的方式显示。
您可以通过向列表视图发送LVM_INSERTITEM消息来向其中添加项目,这时还需要把一个指向LV_ITEM型的结构体的变量的指针放到lParam一同传给列表视图。LV_ITEM的定义如下:
iSubItem 和上一个成员变量指定的项目相连的子项目的索引号。您可以把它当作表单的“列”。譬如您想要把一个项目插入到新创建的列表视图控件,iItem的值应为0(因为该项目是第一个项目),iSubItem的值也应当为0(我们想把该项目插到第一列)。如果你想指定一个子项目和该项目相连,iItem中应该是您想要相连的项目的索引号,iSubItem的值应当是大于0的值,具体的值取决于您想把该子项目插在那一列。如果你的列表视图控件一共有4列的化,第一列包含了项目,其余3列是留给子项目的。如果您想把子项目插在第四列,应当指定该值为3。
LV_ITEM STRUCT
imask dd ?
iItem dd ?
iSubItem dd ?
state dd ?
stateMask dd ?
pszText dd ?
cchTextMax dd ?
iImage dd ?
lParam dd ?
定义一个LV_ITEM型的结构体变量。
给该变量赋给合适的值
如果要插入一个项目,就向列表视图控件发送LVM_INSERTITEM值。 如果要插入一个子项目,发送LVM_SETITEM。如果您不明白项目和子项目之间的关系的话,可能会有一些疑惑。子项目仅是项目的属性而已,也就是说您可以插入一个项目但是不能插入一个子项目。所以添加一个子项目十只能发送LVM_SETITEM消息而不能发送LVM_INSERTITEM消息。
既然我们已经知道了如何创建列表控件,接下来我们学习如何使用它们。我们将主要集中在报告方式的显示上,因为该种方式演示了最多的列表控制的特性。使用列表控制的步骤如下:
调用CreateWindowEx函数来创建一个列表控件,指定它的类名为SysListView32。您还可以在此处指定控件初次显示时的方式。
列表视图控件的消息/通知
既然您知道了如何创建和往其中添加内容,下一步就是如何和它通讯。列表视图控件和它的父窗口之间的通讯是通过消息/通知来进行的。父窗口通过发送消息来控制列表视图控件,列表视图控件通过发送WM_NOTIFY消息来通知它的父窗口。这一点和其它的通用控件没有什么不同。
排序项目/子项目
lParam = pCompareFunction
lParamSort 用户定义的值,该值将传递给用来比较的函数。
pCompareFunction 用户定义的用来比较排序的函数的地址。该函数的原型如下:
CompareFunc proto lParam1:DWORD, lParam2:DWORD, lParamSort:DWORD
LVCF_TEXT = pszText有效.
相关文档
最新文档