win32汇编学习笔记3

来源:互联网 发布:淘宝卖家快速升心 编辑:程序博客网 时间:2024/06/11 02:45

分析简单的win32程序格式

根据以前的小程序样式来简单分析一下:

.386

.model flat,stdcall   这一句是定义内存方式,语言格式

.option casemap:nome   定义大小写敏感

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

;以上几句程序都是必然这么写的,尤其是后两句,是win32

;必然定义格式,除了这些win32 没有别的定义,但是第一

;句伪指令是说明引用cpu指令集的可有很多种选择(详情 

;根据本人上篇日志咯(*^__^*) 嘻嘻……

.data

<这是代码段>定义字符串,常量等

.code    

额这就是代码段了( ⊙ o ⊙ )!

   此处跟dos汇编差不多也是有开始标号   例如

Start:

。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。

End start 

这样来结束程序。(⊙v⊙)嗯

额其中 .stack .data .const .code 都是分段伪指令,但是win32中不必考虑堆栈段,系统会为程序分配一个向下扩展的,足够多大的段作为堆栈,呵呵顺便说一下386的内存分页机制,

Win32 环境的内存管理与之相适应,每个页大约4KB,可以自由指定属性,例如上一个页是代码页,下一个页可能用来存放数据,win32 中的分段实际上就是把不同类型的数据或代码归类,再放到不同的页中去,因为有的数据始可读可写的 ,有的是可读不可写的,等,他们都要放到不同的属性页中去。

我们分开数一下不同的段。

.data 和.data?  .const 定义的都是数据段,但是他们定义的数据具有不同的属性咯。(对应上边说的~\(≧▽≦)/~啦啦啦)

,data 定义的是可读可写的变量,此类数据在原程序中已经具有初始值,可以被更改(在程序执行中),在程序装入内存的时候,装入内存。.data段中存放的信息存放到可执行文件的——DATA节区内。

.data? 可读可写的未定义变量。这些变量一般用来当做缓冲区,或程序执行后才开始使用吗,但是要注意次类数据不会增加可执行文件的大小。但是.data中的数据会增加可执行文件的大小  

.const 段中的数据都是常量,比如-->要现实的字符串,

.code  代码段不过在.code 段中的代码是不可写的,这个不像是dos汇编中可以随便改变代码区代码,但是windows中对代码的执行有特权级,我们的代码都是在3级特权下执行,0级特权是最高的,用户应用程序都是3级特权所以我们根本无法更改代码段。

对于汇编中的“;”就是相当于c语言中的/*  */注释符号  对了关于"\"反斜杠,就是换行的意思,利用这个反斜杠可以将很长的一行程序更改成好几行,

了解一下windows api 

Win32 程序基于api的基础山的 api就是应用程序编程接口application programimg interface 其实就是windows自己封装的函数我们把他包含进去进行调用。Win32的系统功能模块是放在windows 动态链接库dll文件中的,dll是一种windows的可执行文件,采用的是和.exe文件相同的pe格式,

应用程序在使用的时候由windows自动装入dll程序并调用的相应的函数,

实际上windows的基础就是由dll文件组成的,win32 api的核心是由3个dll文件提供,

Kernel32.dll   系统服务功能

User32.dll用户接口服务,建立窗口和传送消息

Gdi32.dll  图形设备接口 利用vga 与drv之类的显示设备驱动程序来完成显示文本和矩形等功能

调用api  

呵呵api就是供我们来调用的因为api里边封装的都是函数,我们调用windows早就编写好的函数,当然我们调用函数总还是会有参数的,以前我们在c或者java中都体验过编程,几乎所有的韩硕都有参数的传递呗,  但是win32 api的参数传递使用堆栈来进行的,调用者把参数压入堆栈,dll中的函数程序再从堆栈中取出参数处理,额在函数值型返回之前,将堆栈中的无用个参数进行恢复,呵呵就是设置栈顶,例如 windows中的 消息框函数声明如下

Int MessageBox(

HWD hWnd,

LPCTSTR lp Text,

LPCTSTR lp Caption,

UINT uType

);

Library:use User32.lib.

呵呵,我们看出来了messageBox函数是有四个参数的,窗口句柄,要显示的字符串地址,标题字符串地址,消息框类型。这四个参数,由于windows使用c编写的所以windows编程资料都是用c格式发布的。

有了函数原型的定义后我们就要调用了,对于调用时的入栈顺序是这样的,最后一个参数先入栈,  所以消息框函数展开是这样的:

Push uType

Push lpCaption

Push lpText

Push hWnd

Call MessageBox

.额下面是时候讲讲invoke语句使用方法了。 对于好几百兆的windows不像dos(几百KB),所以win32函数动辄就是十几个参数是很正常的,正如上面的展示若是没有特殊的伪指令操作我们需要更多的 push指令来压入堆栈,这就导致我们在编程的时候可能遗忘参数的入栈,导致堆栈不对齐就悲剧了。所以invoke伪指令就出现了。Invoke指令的使用格式就是如下

Invoke 函数名,参数一,参数二。。。。。。。

对于MessageBox 函数调用我们就可以解释了

Invoke MessageBox ,NULL,offset szText,offset szCaption,MB_OK

额但是我们要清楚 invoke不是386指令,而是一个masm的伪指令,在进行程序编译的时候会根据参数个数 展开成多个push指令和call 函数名指令,同时进行 参数数量的检查,如果参数和定义参数不一样多的时候,编译器报错。

Error A....:too few arguments to invoke

呵呵以后看到像这样的报错,我们就要去检查参数是否对齐。

Api的函数都是有返回值的,例如前边的messageBox就是返回int 类型, 对于返回值类型的汇编程序来说只有一种dword类型,它永远放到eax中。如果返回值超过了eax的容量那就只好返回一个指针,

呵呵,我们总不能总是单一的调用api函数,我们也会构造自己的函数,对于win32 函数声明格式本人接下来会讲的,其实就算是api函数也是要进行事先声明的。 Win32函数声明格式如下

函数名 proto 距离 语言 参数一:数据类型,参数二:数据类型。。。。。。。。。。。

额proto  是函数声明的伪指令,距离可以是 NEAR FAR NEAR16.NEAR32 FAR16,FAR32等由于win32中只有一个平坦的段flat 那也就无所谓距离了。= =所以定义都是忽略的,语言类型都是model类型的,如果忽略就代表使用默认值呗,额对于参数名称win32可以进行忽略不写,记得我们在c中也是这样的呀, 例如  int change(int,int);参数变量名字也可以,但是对于数量么,还是严格要求的,

额对于include语句。。我们也是有话说的。

我们使用文件头包含,就是把原先定义好的接口,函数声明包含进来供我们使用,其实每个dll 都对应<dll名.inc>文件,所以在与程序中把他包含进来就行了。例如  

Include《user32.inc》

特别注意当多个源程序用到相同的函数定义,常量定义,等的时候我们可以吧这些相同的部分,写成文件,使用include包含到所需原程序中区就行了。

当关键字和文件名同名时(这样会引发混淆错误)时,我们可以用《》将文件名包含起来。

关于api的等值定义。

  额这些我就不用多列举了。MB_HELP消息框上显示 帮助

MB_OK  消息框上显示 确定

MB_YENO 消息框上显示 是和否

以下是显示图标的

MB_ICONWARING  显示警告图标 呵呵就是那个 感叹号

等等这些都不列举了。不过这些定义代替了dos中的数值定义 赋予了显而易见的符号我们一看就懂,不像dos中 例如进行输出需要进行软中断的调用 

Mov ah,9

Int 21h 这些 我们只能死寂,呵呵。。

   额鉴于宿舍快要关灯了,本人就就此休息咯,,如有什么错误请求斧正,谢谢。

http://sela365.com/space.php?do=blog&view=me 

哥们建立的网站,帮帮加加人气儿。。谢谢咯。。

原创粉丝点击