windows command line Win32汇编学习(3):简单的窗口(3)

电脑杂谈  发布时间:2018-02-07 10:08:49  来源:网络整理

.CODE
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
.....
end start

.CODE "分段"包含了您应用程序的所有代码,这些代码必须都在 .code 和 end 之间。至于 label 的命名只要遵从 Windows 规范而且保证唯一则具体叫什么倒是无所谓。我们程序的第一条语句是调用 GetModuleHandle 去查找我们应用程序的句柄。在Win32下,应用程序的句柄和模块的句柄是一样的。您可以把实例句柄看成是您的应用程序的 ID 号。我们在调用几个函数是都把它作为参数来进行传递,所以在一开始便得到并保存它就可以省许多的事。

特别注意:WIN32下的实例句柄实际上是您应用程序在内存中的线性地址。

WIN32 中函数的函数如果有返回值,那它是通过 eax 寄存器来传递的。其他的值可以通过传递进来的参数地址进行返回。一个 WIN32 函数被调用时总会保存好段寄存器和 ebx,edi,esi和ebp 寄存器,而 ecx和edx 中的值总是不定的,不能在返回时应用。特别注意:从 Windows API 函数中返回后,eax,ecx,edx 中的值和调用前不一定相同。当函数返回时,返回值放在eax中。如果您应用程序中的函数提供给 Windows 调用时,也必须遵守这一点,即在函数入口处保存段寄存器和 ebx,esp,esi,edi 的值并在函数返回时恢复。如果不这样一来的话,您的应用程序很快会崩溃。从您的程序中提供给 Windows 调用的函数大体上有两种:Windows 窗口过程和 Callback 函数。

如果您的应用程序不处理命令行那么就无须调用 GetCommandLine,这里只是告诉您如果要调用应该怎么做。

下面则是调用WinMain了。该函数共有4个参数:应用程序的实例句柄,该应用程序的前一实例句柄,命令行参数串指针和窗口如何显示。Win32 没有前一实例句柄的概念,所以第二个参数总为0。之所以保留它是为了和 Win16 兼容的考虑,在 Win16下,如果 hPrevInst 是 NULL,则该函数是第一次运行。特别注意:您不用必须声明一个名为 WinMain 函数,事实上在这方面您可以完全作主,您甚至无须有一个和 WinMain 等同的函数。您只要把 WinMain 中的代码拷到GetCommandLine 之后,其所实现的功能完全相同。在 WinMain 返回时,把返回码放到 eax 中。然后在应用程序结束时通过 ExitProcess 函数把该返回码传递给 Windows 。

WinMain proc Inst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD 

上面是WinMain的定义。注意跟在 proc 指令后的parameter:type形式的参数,它们是由调用者传给 WinMain 的,我们引用是直接用参数名即可。至于压栈和退栈时的平衡堆栈工作由 MASM 在编译时加入相关的前序和后序汇编指令来进行。 LOCAL wc:WNDCLASSEX LOCAL msg:MSG LOCAL hwnd:HWND LOCAL 伪指令为局部变量在栈中分配内存空间,所有的 LOCAL 指令必须紧跟在 PROC 之后。LOCAL 后跟声明的变量,其形式是 变量名:变量类型。譬如 LOCAL wc:WNDCLASSEX 即是告诉 MASM 为名字叫 wc 的局部边量在栈中分配长度为 WNDCLASSEX 结构体长度的内存空间,然后我们在用该局部变量是无须考虑堆栈的问题,考虑到 DOS 下的汇编,这不能不说是一种恩赐。不过这就要求这样声明的局部变量在函数结束时释放栈空间,(也即不能在函数体外被引用),另一个缺点是您因不能初始化您的局部变量,不得不在稍后另外再对其赋值。


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-65573-3.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...