小俊 发表于 2017-12-26 11:25

【原创】如何使用VS自带工具写Windows汇编程序 Ⅰ

本帖最后由 小俊 于 2017-12-26 11:36 编辑

首先,先说一下我的环境
Windows10版本,和Windows SDK版本都是目前最新的 版本为:1709(16299)
VisualStudio也是最新的 <VC++ 2017 v141 工具集(x86,x64)>

编写Windows程序,当然需要用到Windows API,目前讲两种方式

[*]动态获取函数地址,在这里我就不过多讲解,有兴趣看我前两篇帖子
[*]正常方式,这就是我接下来要讲的了,导入Lib库,然后声明函数原型,就可以直接调用了
32位Lib路径为:C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\x86
最重要的俩个库为:kernel32.Lib User32.Lib 吧这俩个库拷贝到我们的源码目录

然后在代码中导入
;导入Lib库
includelib kernel32.Lib
includelib User32.Lib
声明函数原型,例如:
ExitProcess proto,dwExitCode:dword
MessageBoxA proto,hWnd:dword,pText:dword,pTitle:dword,uType:dword
调用函数:例如
invoke MessageBoxA,0,0,0,0
invoke ExitProcess,0
整体代码:
.386
.model flat,stdcall
option casemap:none

;导入Lib库
includelib kernel32.Lib
includelib User32.Lib

;声明函数原型
ExitProcess proto,dwExitCode:dword
MessageBoxA proto,hWnd:dword,pText:dword,pTitle:dword,uType:dword

;代码段
.code
main:
      invoke MessageBoxA,0,0,0,0
      invoke ExitProcess,0
end main
这里,我再为小白解释一下代码,老鸟跳过
.386 为指令集,微软的解释:https://msdn.microsoft.com/zh-cn/library/ss9fh0d6.aspx

除了386,Masm还支持以下指令集

.Model 我个人理解为指定内存模型,微软的解释:https://msdn.microsoft.com/zh-cn/library/ss9fh0d6.aspx
第一个参数基本为(必选):FLAT
第二个为调用约定:常用的有两种STDCALL, C
FLAT 为平坦模式,学过80386的应该都找到,寻址方式都为段加偏移,而平坦模式段基址都为0(fs,gs除外)所以平坦模式线性地址等于虚拟地址
STDCALL调用约定和C的调用约定 区别就是一个内平衡栈 ,一个外平衡栈 ,入栈顺序都是从右向左依次入栈
option casemap:none 为区分大小写,没什么好解释的了
proto 声明函数原型
invoke 调用函数
这俩个是Masm的伪指令,并不是汇编
例如:
invoke ExitProcess,0
等于:
push 0
call ExitProcess

https://static.52pojie.cn/static/image/hrline/4.gif


接下来吧代码进行编译,这里用到俩工具:ml.exe link.exe
32位路径为:C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\bin\Hostx86\x86
再我电脑上路径为这个,你电脑我就不确定了。但是这个不重要,如果你电脑上装了VS的话,那么你的开始菜单里面应该有 VS 2017的开发人员命令提示符

输入ml,出现这些信息,说明环境没问题

然后将路径切换到我的源代码路径
cd C:\Users\XiaoJun\Desktop\Source
然后直接编译
ml Source.asm

恭喜,没有出现警告或者错误
生成了三个文件

运行

没有问题,弹出了个啥也没有的消息框,因为我们给的参数都是0
运行没有问题,我们进一步做一些优化
首先,我为什么用汇编写程序,因为小,而且不依赖C运行时库,不会生成无用代码
但是我一查看文件属性,居然还有2.5k这是我接受不了的,一共这才几条汇编代码

我心算了一下,PE头0x200(512)个字节, .text 代码段0x200(512)个字节,导入表在 .data段0x200(512)字节,一共应该是1.5k才对呀
所以我打开010Editor一探究竟

发现多了个 .reloc 段,并且PE头占用了0x400(1024)个字节,所以才会那么大
因为多了个.reloc 段,PE头也会多个区段表,所以0x200(512)个字节不够,所以PE头才变成了0x400(1024)个字节
问题找到了,是因为编译器默认开启了随机基址为了修复IAT而产生的重定位,我们关闭随机基址试一试,这里重新用link.exe连接一下
link Source.obj /DYNAMICBASE:NO注:(/DYNAMICBASE:NO 为关闭随机基址)

再来查看一下文件大小

和我预期的一样,变成了1.5k
完善一下代码
.386
.model flat,stdcall
option casemap:none

;导入Lib库
includelib kernel32.Lib
includelib User32.Lib

;声明函数原型
ExitProcess proto,dwExitCode:dword
MessageBoxA proto,hWnd:dword,pText:dword,pTitle:dword,uType:dword

;只读数据段
.const
      lpStr   db "Hello World!",0
      lpTitle db "Title",0

;代码段
.code
main:
      invoke MessageBoxA,0,offset lpStr,offset lpTitle,0
      invoke ExitProcess,0
end main
编译 ml Source.asm /link /DYNAMICBASE:NO /SUBSYSTEM:WINDOWS 注:(/SUBSYSTEM:WINDOWS表示生成窗口程序,没有控制台啦)

编译成功,没有警告或者错误

运行成功,没有问题,黑色的框框也没啦



参考:
http://kipirvine.com/asm/gettingStartedVS2017/index.htm
https://msdn.microsoft.com/zh-cn/library/hb5z4sxd.aspx
https://msdn.microsoft.com/zh-cn/library/y0zzbyt4.aspx

小俊 发表于 2018-1-16 15:51

pojiezhe 发表于 2018-1-16 13:12
楼主,你好,问一下三个问题。
1.WIN10   64位的怎么去找到lib库的那两个文件呢?
2.VS2017开发人员命令 ...

需要下载的软件:
    1. Windows 10 SDK   下载地址:https://developer.microsoft.com/zh-cn/windows/downloads/windows-10-sdk
    2. Visual Studio          下载地址:https://www.visualstudio.com/
    3. 记事本,windows自带
第一个问题,lib库在Windows 10 SDK有
第二个问题,VS2017开发人员命令提示符 ,安装了Visual Studio就有了

pojiezhe 发表于 2018-1-16 13:12

wei1355188058 发表于 2017-12-26 13:44

不错学习C++,了解一下汇编。。。。。。。。

lzlv312 发表于 2017-12-31 19:01

教程贴总是没人吗

haoqwenie 发表于 2018-1-2 07:08

完全没看懂

pojiezhe 发表于 2018-1-16 23:25

LDM233 发表于 2018-1-28 19:00

真的良心帖,顶!

sdbz001 发表于 2018-3-7 15:25

真的良心帖,顶!

村民 发表于 2018-3-7 23:32

真的良心帖,支持
页: [1] 2
查看完整版本: 【原创】如何使用VS自带工具写Windows汇编程序 Ⅰ