c语言 宏定义 64位变量,【图片】初试64位宏汇编(努力构造了一个“invoke”宏)_汇编吧_百度贴吧...
发布日期:2021-06-24 13:44:35 浏览次数:2 分类:技术文章

本文共 3549 字,大约阅读时间需要 11 分钟。

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

///代码第二部分

;==============================================================

; 声明要用到的包含文件

;include “m64.inc”;呵呵,这是我将放上面几个宏的包含文件

; 外部函数声明【示例中只用到少数几个API,所以没有去折腾“Kernel32.inc”、“msvcrt.inc”】

extrn ExitProcess: proc; Kernel32.dll、Kernel32.lib[、Kernel32.inc]

extrn GetVolumeInformationA: proc; Kernel32.dll、Kernel32.lib[、Kernel32.inc]

extrn printf: proc; msvcrt.dll、msvcrt.lib[、msvcrt.inc]

; 测试用数据

.const

nC1dq0h

nC2dq0FFFFFFFFFFFFFFFFh

nC3dq0h

nC4dq0h

nC5dq0h

nC6dq0h

.data

_pFuncdq?;函数指针

;GetVolumeInformationA函数使用的数据【◆用的是64位的,但仍按照win32 api里定义的参数长度进行定义】

szVolumelabeldb 64 DUP(0); 函数返回卷标用

nSerialNumberdd?; 函数返回系列号用

nMaxCLengthdd?; 函数返回最大文件名长度用

nFileSysFlagdd?; 函数返回文件系统标识用

szFileSysNamedb100 DUP(0); 函数返回文件系统名称用

;◆转义符测试用数据。ml64不支持转义符,不会把“\n”解释成0x0A的!

szMsgdb 0Ah, 0Dh, "Volumelabel = %s", 0Ah, 0Dh, 0

; 代码

.code

; 测试用函数【自己写的函数,名称前加下划线是我的习惯。呵呵】

;_Func proc;有效

;_Func proc _param1:QWORD, _param2:QWORD, _param3:QWORD, _param4:QWORD, _param5:QWORD, _param6:QWORD;有效

_Func proc uses rbx _param1:QWORD, _param2:QWORD, _param3:QWORD, _param4:QWORD, _param5:QWORD, _param6:QWORD;设定rbx会被改变

ret

_Func endp

;附:自定义函数“_Func”的反汇编代码:

;0000000001271000 | 55 | push rbp

;0000000001271001 | 48:8BEC | mov rbp,rsp ;ml64依然像masm32一样,采用STDCall

;0000000001271004 | 53 | push rbx ;uses rbx

;0000000001271005 | 5B | pop rbx

;0000000001271006 | C9 | leave ;即:mov rsp,rbp/pop rbp

;0000000001271007 | C3 | ret

main proc

; 测试局部变量的定义【默认是DWORD】

local@szTmpBuf[150], @dwCount

local@pMaxCLength:QWORD, @pFileSysFlag:QWORD;存放变量指针

; ★指令测试:AMDx64 PUSH指令不支持64位立即数。push指令支持的最大立即数是0x7FFFFFFF

;push0F000000000000000h;◆错误:操作数无效

; 装填函数指针

movrax, offset _Func

mov_pFunc, rax

; 测试函数调用【“invoke”宏不负责检测参数数量,呵呵】

invoke_Func, rcx, rdx; 仿masm32的函数调用方式

invoke_pFunc, rcx, rdx; 仿masm32的函数指针调用方式

xorrbx,rbx; 示例而已,不取当前实例的加载基址了

invoke[rbx + _pFunc], rcx, rax; 仿masm32的重定位写法(rbx中应该是实例加载后的实际内存基址)

; 多参数(超过4个参数时)函数调用测试

invoke_Func, nC1, nC2, nC3, nC4, nC5, nC6;

invoke_Func, nC1, 7FFFFFFFh, _TXT("Hello!\n"), nC4, nC5, nC6; 测试立即数和字符串直接作为参数

;invoke_Func, nC1, 255, nC3, nC4, nC5, _TXT("Hello!\n"); 错误:第6个参数是64位立即数,push指令不支持

; 用64位API来测试,专门找了一个参数超多、又没有结构参数的API:GetVolumeInformationA(Kernel32.dll)

; 函数定义见代码后面的“附录三”

addrsp, 8*8

movrax, offset nMaxCLength

mov@pMaxCLength, rax

learax, nFileSysFlag

mov@pFileSysFlag, rax

learax, szFileSysName

; ◆错误:“invoke”宏不支持“offset”操作符、也不能像masm32那样支持“addr”伪操作符

;invokeGetVolumeInformationA, _TXT("C:\\"), offset szVolumelabel, 255, offset nSerialNumber, offset nMaxCLength, offset nFileSysFlag, offset szFileSysName, 255;错误

; ◆错误:“_ADDR”宏返回的是64位地址,参数5~8是通过栈传递的,使用“_ADDR”的结果,就成了“push 立即数地址”,像前面的指令测试,肯定不行!

;invokeGetVolumeInformationA, _TXT("C:\\"), _ADDR(szVolumelabel), 255, _addr(nSerialNumber), _addr(nMaxCLength), _addr(nFileSysFlag), _ADDR(szFileSysName), 255

; ★完全正确的写法:

invokeGetVolumeInformationA, _TXT("C:\\"), _ADDR(szVolumelabel), 255, _addr(nSerialNumber), @pMaxCLength, @pFileSysFlag, rax, 0FFh;OK!!!

; ★伪指令测试。不支持伪指令.if/.ifend、.while/.endw :(

;.if!rax

;int3

;.endif

oreax, eax

jz_err

@@:

invokeprintf, _TXT("Volumelabel = %s\n"), _addr(szVolumelabel);◆ml64不会把“\n”解释成0x0A的!

invokeprintf, _addr(szMsg), _ADDR(szVolumelabel)

int3; ◆未设置控制台(窗口会一闪而过),也不想使用“MessageBox”(在“User32.dll”里),

; 而且也需要看反汇编代码,顺带测试“invoke”宏,故强置断点!(建议使用x64dbg调试器)

; ◆不屏蔽掉此句,直接运行“invoke.exe”会在看到控制台窗口的同时,弹出带调试按钮的窗口(应用程序错误)

; 如果系统已经有了默认调试器,则应用程序错误的窗口不会出现,而是直接呼叫出调试器来......

; 退出(使用“ExitProcess”的话,后面的"ret"似乎成了多余...)

;xorrcx, rcx

;callExitProcess; ml64正规写法来调用“ExitProcess”

ret

_err:

invoke printf, _TXT("\n\rFunction GetVolumeInformationA run error!\n\r")

;int3

jmp @B

main endp

end

转载地址:https://blog.csdn.net/weixin_33239721/article/details/117109086 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:标识符可以由汉字组成 c语言,C语言程序设计考题
下一篇:c语言自定义scopy,C++自定义复制构造函数详解

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年04月10日 21时51分08秒