Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释

抱歉,还是只能用米国的软件以及技术以及等等等等。。。。。。,所以各位勿怪。

如果配置完成,在vs2022调试环境下正确编译运行后,可以看到如下画面:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第1张图片

在VS022中开发学习汇编必然很方便。

这里可以下载vs2022项目源码: vs2022中Win32汇编(MASM32)环境配置和测试源码-桌面系统文档类资源-CSDN下载

注意, AsmDude(GitHub - vilyLei/asm-dude: Visual Studio extension for assembly syntax highlighting and code completion in assembly files and the disassembly window)只支持到vs2019。

主要配置过程如下:

step1: 按照vs2022(直接官网下载Community版本)

step2:Download The MASM32 SDK这里下载masm32v11r.zip这个压缩包

step3: 将MASM32的install.exe运行安装到C盘(也可以是别的盘),安装过程注意同意其解压,这里会耽搁一小段时间。

step4: 在vs2022中建立一个控制台应用。删除原来默认生成的cpp文件

step5: 在项目图标上上右键, 生成依赖项->生成自定义->选中masm, 如下图:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第2张图片

step6: 在源文件图标上右键,添加 -> 新建项, 新建 test.asm文件。

step7: 在test.asm写入代码如下:

.386
.model flat, stdcall
.stack 4096
option casemap:none

include		windows.inc
include		user32.inc
includelib	user32.lib
include		kernel32.inc
includelib	kernel32.lib

.const

szCaption	db	'恭喜',0
szText		db	'Win32汇编程序成功编译!',0

.data

ExitProcess proto, dwExitcode: dword
; 代码段
.code
mainT PROC
	invoke	MessageBox,NULL,offset szText,offset szCaption,MB_OK
	invoke	ExitProcess,NULL

mainT ENDP

END mainT

// 部分代码源自 <<[琢石成器—Windows环境下32位汇编语言程序设计].罗云彬.第三版>>

上面代码中的 mainT是我这里为了解释如何配置而故意起的名字。

step8: 设置test.asm属性。在test.asm文件图标上点击右键->属性, 在弹出的界面设置如下图示:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第3张图片

step9: 设置解决方案平台配置为x86,如下图。

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第4张图片

step10: 在项目图标上右键,属性,设置程序入口为mainT,如下图:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第5张图片

step11: 配置MASM32库目录。我的masm32安装目录是 C:\masm32, 所以才有如下图示的相关路径配置:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第6张图片

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第7张图片

step12: 平台工具集的相关设置。右键项目图标,打开属性界面,设置如下:

首先看到的是如下界面:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第8张图片

设置完成应用之后是就会变成如下图所示的界面: 

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第9张图片

注意,默认vs2022所带的平台工具集版本版本较高,无法正常支持masm32, 需要按照低版本的工具集。(vs2022顶部主菜单)工具 -> 获取工具和功能 -> 修改,如下图:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第10张图片

至此,设置完成,可以运行了。 

再写一个 message box中的hello world显示代码:

.386
.model flat, stdcall
.stack 4096
option casemap:none

include		windows.inc
include		user32.inc
includelib	user32.lib
include		kernel32.inc
includelib	kernel32.lib

.data
	szCaption	db	'A MessageBox !',0
	szText		db	'Hello, World !',0
; 代码段
.code
mainT PROC
	invoke	MessageBox,NULL,offset szText,offset szCaption,MB_OK
	invoke	ExitProcess,NULL

mainT ENDP

END mainT

调用成功如下图:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第11张图片

注意:

1. 防止 LNK2026    模块对于 SAFESEH 映像是不安全的 这个错误(release环境下)导致编译运行问题在属性窗口->连接器->命令行 里做如下图的设置(/SAFESEH:NO):

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第12张图片

2. 非法(错误的)访问不应该访问的内存区域会报 处有未经处理的异常: 0xC0000005: 执行位置 0x00585022 时发生访问冲突 这种错误。例如 asm代码中将函数定义在数据区就会报这个错误。下面是示例代码:

	.386
	.model flat, stdcall
	.stack 4096
	option casemap:none
	
; include some libs
	include		windows.inc
	include		kernel32.inc
	includelib	kernel32.lib

; data section
	.data
		szText		db	'Hello, MASM PROC !',0

	; 因为这个函数定义在数据区(段),数据区是不具备可执行属性的,所以调用此函数会报 处有未经处理的异常: 0xC0000005: 执行位置 0x00585022 时发生访问冲突
	ErrorDefineFunc	proc	c uses eax ecx param0, param1
						mov		eax, param0
						mov		ecx, param1
						add		eax, ecx
						ret
	ErrorDefineFunc	endp
	.code
; define some proc
	; 定义在代码区域(段)内,能正确访问
	CorrectDefineFunc	proc	stdcall uses eax ecx param0, param1
						mov		eax, param0
						mov		ecx, param1
						add		eax, ecx
						ret
	CorrectDefineFunc	endp

	mainT proc
			; 调用此函数会出现崩溃错误:执行位置 0x00585022 时发生访问冲突
			;invoke		ErrorDefineFunc, 1, 2
			; 能正确调用此函数
			invoke		CorrectDefineFunc, 1, 2

			xor			eax, eax
			invoke		ExitProcess,NULL
	mainT endp
	end
; 注意 0x00585022 这个内存位置是的的值和运行时具体使用的内存有关

上面的汇编代码编译为Debug程序再反汇编如下图:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第13张图片

上图中的一些指令:

        INT3指令: Debugger breakpoint trap.

        RETN指令:The ret instruction pops and jumps to the return address on the stack. A nonzero #n in the RET instruction indicates that after popping the return address, the value #n should be added to the stack pointer. RETN 8也就是 stack(栈) pop 8个字节。在这个程序里面也就是 ESP += 8。之所以8个字节,因为函数调用的时候,为了传参数,push了一个dword(4字节) 的2和一个dword(4字节) 的1,push一次执行一次ESP -= 4操作。注意,这里的操作全部是内存地址上的操作。

        LEAVE指令:Tear down stack frame, 相当于如下汇编代码:

mov esp, ebp
pop ebp

        因为进入函数的时候,执行了如下代码:

PUSH EBP
MOV EBP, ESP

        因此函数返回之前要执行 LEAVE 指令。

汇编指令细节详见: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/x86-instructions


一些x86伪指令(例如 .data, .code, invoke, proc 等等):

PROC | Microsoft Docs

伪指令由汇编编译器翻译为对应的汇编代码(指令),用了伪指令能方便开发者写程序,但是也因为隐藏了细节而造成一些麻烦。因此,需要通过汇编程序编译出来之后再反汇编才能看到真正的汇编代码或指令。注意Release版本反汇编看到的汇编代码和Debug版本反汇编看到的汇编代码是有区别的。

上面的汇编代码编译为Release程序再反汇编如下图:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第14张图片

3.查看寄存器相关信息(寄存器中的值)

        第一步, 在汇编源程序中设置断点,运行并进入调试状态。

        第二步,vs顶部主菜单中选择: 调试 -> 窗口 -> 寄存器。就可以看到各个寄存器的值了。

        第三步,在显示寄存器值得区域内点金右键,弹出菜单,就可以选择显示 标志寄存器、MMX、SSE等状态信息了。如下图:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第15张图片

可以和ARM(Advanced RISC Machines)处理器的寄存器做个比较,ARM 寄存器如下图:

Win10系统VS2022开发环境中(X86)Win32汇编(MASM32)环境配置和一些示例源码及解释_第16张图片

上图源自: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/third-party/ddi0100e_arm_arm.pdf

一些汇编相关的资料:

https://www.cs.virginia.edu/~evans/cs216/guides/x86.pdf

https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf

https://docs.oracle.com/cd/E19641-01/802-1948/802-1948.pdf

CS107 Guide to x86-64

windows api:

WriteConsole function - Windows Console | Microsoft Docs

你可能感兴趣的:(Assembly,系统,assembly)