JWASM x64语法
来源:互联网 发布:ruby编程语言 pdf 编辑:程序博客网 时间:2024/06/05 19:03
写32位汇编时,JWASM基本与MASM相同,写64位汇编时,JWASM与MASM区别较大,因JWASM支持高级语法,如.if,.while,invoke等等,且支持自动控制堆栈(和写32位汇编一样)。
我们依旧以经典的HelloWorld来做为例子
注:关于Win64调用约定详细参考Win64调用约定
简单说一下Win64的调用约定吧,即函数的前4个参数通过寄存器传递,分别为rcx, rdx, r8, r9,其余参数通过堆栈(即push)传递。但64位下堆栈由Caller(调用者)分配,所以调用函数前都要先预留堆栈空间,至少要【 8 * 参数个数】个byte,MSDN堆栈分配
Win64与Win32数据类型区别:int与long依旧为32 bits(Linux64下long类型为64 bits),Pointer为64 bits,用64 bits类型用int64或longlong,MSDN说这是为了节约内存。详细见MSDN标量类型
先看一下Jwasm_HelloWorld.asm
option win64:1option frame:autooption casemap:none.nolist.nocref.NOLISTMACROinclude ..\macros.inc ;;此文件为MASM SDK中的macros.inc,里面的UCCSTR宏,定义Unicode字符串;include windows.inc ;;这些inc文件全来自MASM SDK,不过里面的一些定义被我手动修改了 ;;如HINSTANCE定义,改为qword了,为了代码可直接使用, ;;我将用到的定义写出来了;include kernel32.inc;include user32.inc;includelib kernel32.lib;includelib kernel32.lib.list.crefMB_OK equ 0NULL equ 0TRUE equ 1HINSTANCE typedef QWORDLPSTR typedef QWORDGetModuleHandleW proto :qwordGetCommandLineW protoMessageBoxW proto :qword, :qword, :qword, :qwordExitProcess proto :qwordGetModuleHandle equ <GetModuleHandleW>GetCommandLine equ <GetCommandLineW>MessageBox equ <MessageBoxW>.dataUCCSTR szMsgTitle,"x64",0UCCSTR szMsgContent, "Hello World",0.code_start proc frame local hInstance:HINSTANCE, lpCommandLine:LPSTR ;;为了测试语法,所以将这2个变量保存在堆栈上了 invoke GetModuleHandle, NULL mov hInstance, rax invoke GetCommandLine mov lpCommandLine, rax invoke MessageBox, NULL, addr szMsgContent, addr szMsgTitle, MB_OK invoke ExitProcess, NULL ret_start endp@Test proc frame numb1:qword, numb2:qword, numb3:qword ;;此函数为JWASM语法示范 mov rax, TRUE ret@Test endpend _start
下面是用MASM x64(即ML64)写Masm_HelloWorld.asm
option casemap:none.nolist.nocref.NOLISTMACROinclude macros.inc.list.crefMB_OK equ 0NULL equ 0HINSTANCE typedef QWORDLPSTR typedef QWORDGetModuleHandleW proto :qwordGetCommandLineW protoMessageBoxW proto :qword, :qword, :qword, :qwordExitProcess proto :qwordGetModuleHandle equ <GetModuleHandleW>GetCommandLine equ <GetCommandLineW>MessageBox equ <MessageBoxW>.dataUCCSTR szMsgTitle,"x64",0UCCSTR szMsgContent, "Hello World",0.code_start proc FRAME local hInstance:HINSTANCE, lpCommandLine:LPSTR push rbp .pushreg rbp mov rbp, rsp .setframe rbp, 0 sub rsp, 16 ;分配堆栈,2个64 bits变量,即hInstance, lpCommandLine .allocstack 16 .endprolog sub rsp, 1 * 8 ;分配堆栈,1个参数 mov rcx, NULL call GetModuleHandle ;invoke GetModuleHandle, NULL add rsp, 1 * 8 ;收回堆栈空间 mov hInstance, rax sub rsp, 0 ;无参数,这个指令只是为说明堆栈分配,实际中可以省略 call GetCommandLine ;invoke GetCommandLine add rsp, 0 ;收回堆栈空间 mov lpCommandLine, rax sub rsp, 4 * 8 ;分配堆栈,MessageBox函数有4个参数 mov rcx, NULL lea rdx, szMsgContent lea r8, szMsgTitle mov r9, MB_OK call MessageBox ;invoke MessageBox, NULL, addr lpMsgContent, addr lpMsgTitle, MB_OK add rsp, 5 * 8 ;收回堆栈 sub rsp, 1 * 8 ;分配堆栈 mov rcx, NULL call ExitProcess ;invoke ExitProcess, NULL add rsp, 1 * 8 ;收回堆栈 add rsp, 16 pop rbp ret _start endp_start_Op proc FRAME ;;此函数为_start函数优化后的样子, local hInstance:HINSTANCE, lpCommandLine:LPSTR push rbp .pushreg rbp mov rbp, rsp .setframe rbp, 0 sub rsp, 16 .allocstack 16 .endprolog sub rsp, 4 * 8 ;;只在开始处为【call函数】时分配一次堆栈空间 mov rcx, NULL call GetModuleHandle ;invoke GetModuleHandle, NULL mov hInstance, rax call GetCommandLine ;invoke GetCommandLine mov lpCommandLine, rax mov rcx, NULL lea rdx, szMsgContent lea r8, szMsgTitle mov r9, MB_OK call MessageBox ;invoke MessageBoxW, NULL, addr lpMsgContent, addr lpMsgTitle, MB_OK mov rcx, NULL call ExitProcess ;invoke ExitProcess, NULL add rsp, 4 * 8 ;;收回为【call函数】时分配的空间 add rsp, 16 pop rbp ret_start_Op endpend
Masm_HelloWorld.asm可用ML64或JWASM编译,而Jwasm_HelloWorld.asm只能用JWASM编译,因里面用到高级语法与JWASM特有的指令(option win64, option frame)
Ml64的编译命令:
ml64.exe /c /WX /Zi /Fl"Masm_HelloWorld.lst"/Zd "Masm_HelloWorld.asm"JWASM编译命令:
jwasm.exe -Fl"Masm_HelloWorld.lst" -c -win64 -Zi -Zd "Masm_HelloWorld.asm"jwasm.exe -Fl"Jwasm_HelloWorld.lst" -c -win64 -Zi -Zd "Jwasm_HelloWorld.asm"JWASM的-c必须存在,因JWASM不支持调用Link程序,-c只是为兼容MASM-Fl同MASM,可以看出,编译命令几乎都没变,只是将“/”转为“-”
以下是链接命令,一种是用GoLink链接,一种是微软的Link链接
GoLink.exe /entry _Start /debug dbg /mix /fo HelloWorld.exe HelloWorld.obj kernel32.dll user32.dlllink.exe HelloWorld.obj /entry:_Start /debug /machine:x64 /out:HelloWorld.exe /subsystem:windows /defaultlib:kernel32.lib user32.lib
编译完成后,查看List清单文件,Jwasm_HelloWorld.list中的_start函数几乎与Masm_HelloWorld.list的相同,唯一不同在于sub rsp,Number中的Number,因Masm_HelloWorld.asm中的堆栈分配为人工,为了示范Win64堆栈分配我只是分配了刚好的空间,没有富余。而Jwasm_HelloWorld.asm中,因使用了option win64 指令,所以Jwasm自动帮我们分配了4*8 byte堆栈空间。
下图为Jwasm_HelloWorld.list中_start函数内容
下图为Jwasm_HelloWorld.list中@Test函数内容
Masm_HelloWorld.list就不再贴图了,其指令与Masm_HelloWorld.asm相同
option win64:number 用为允许Jwasm自动分配堆栈的方法和是否自动保存寄存器数据(即函数的前4个参数)至堆栈上。
当number的第1 bit为0时(option win64:2),在函数中,Jwasm不会自动保存寄存器中的参数至堆栈上
当number的第1 bit为1时(option win64:1),JWASM会自动将寄存器中的参数保存至堆栈上,如Jwasm_HelloWorld.list中@Test函数
当number的第2 bit为0时(option win64:1),遇到invoke时,每次都会自动分配堆栈,且最少分配4 * 8 byte(即rcx, rdx, r8, r9),如Jwasm_HelloWorld.list中_start函数中每次遇到invoke指令都会分配4 * 8byte的空间,即sub rsp, 32
当number的第2 bit为1时(option win64:3),只在函数入口处分配一次堆栈(8 * 此函数内invoke参数的最大个数),如MASM_HellowWorld.asm中_start_Op函数一样
OPTION FRAME:<AUTO | NOAUTO> 默认为noauto。此指令影响64位汇编,
当此指令设置为auto且函数声明中带有frame指令时(_start proc frame),JWASM自动生成ML64的Prolog指令(.pushreg,.setframe,.endprolog等等),
JWASM中新增的指令还有很多,如option FieldAlign,option elg,option mz,option DLLImport,option codeview等等,但在HelloWold中没有用到,所以有时间了再翻译下JWASM的帮助文件吧
- JWASM x64语法
- JWASM x64语法
- JWasm masm语法 多平台,支持16~64位
- JWASM简介
- JWasm使用VS2012在win64位建立MASM语法的IDE
- JWasm 跨平台汇编开发
- JWasm 64位下MASM编译器的优选可支持多平台
- x64 primer
- Detours x64
- x86 X64
- wamp x64
- x86, x64
- x64 Architecture
- x86,x64
- X64 笔记
- x64记录
- x86 x64
- PspGetBaseTrapFrame(x64)
- 目标跟踪
- java调用他人网上或是数据库接口,拒绝访问_buaa.edu_1406
- Android 上传自己的开源库到Bintray
- response乱码 response.setCharacterEncoding("UTF-8")不生效的原因及解决方法
- Linux网络编程二
- JWASM x64语法
- ssh学习总结
- ucos ii 软件定时器,delay函数
- php字符串函数相关试题场景
- 学习笔记:C++ 函数重载
- bug排坑记录
- CC2541 软件I2C
- SAP固定资产的几个关键日期
- Planet: Understanding the Amazon from Space 获奖者心得