找回密码
 欢迎注册
楼主: gxqcn

[讨论] 用vc2008开发64位程序,懂的请进

[复制链接]
发表于 2011-4-21 10:32:37 | 显示全部楼层
对于ml64.exe 均使用_fastcall方式,用masm64写独立汇编时还有其他很多不便之处,相比masm32。 Win64汇编语言与C语言混合编程 如果习惯了masm语法,个人推荐用JWasm。 1. JWasm is written in C ,开源。 2. C header files can be converted to include files ,所用头文件由sdk之类的c头文件所转,继承了c头文件多选择式定义的优点,比如32位64位头文件均可在一个文件中定义。 3. SSE4.2 are supported 4.precompiled JWasm binaries are available for DOS, Windows and Linux. For OS/2 and FreeBSD, makefiles are supplied. 多平台。 5.JWasm is faster than Masm. 6.JWasm is free, no artificial license restrictions, can be used to create binaries for any OS. 7.JWasm is a free MASM-compatible assembler . masm32编写的源文件可以不加修改的用JWasm编译。 汇编器JWASM.EXE 集成了16,32,64位的编译模式,masm高级语法被一致支持,比如.if .endif ,ml64.exe则不包含;调用规则也具多样性,不再是ml64.exe单纯的fastcall。 如果头文件定义的很好,写一个程序,加上不同的编译选择,就有可能生成32位,64位的可执行文件。 形如编译命令:
  1. ;--- Win32/64 console application, uses WinInc v2+.
  2. ;--- It can be used to generate both Win32 and Win64 binaries:
  3. ;--- 32bit:
  4. ;--- jwasm -coff -I\WinInc\Include WinXX_1.asm
  5. ;--- link /subsystem:console /Libpath:\WinInc\Lib WinXX_1.obj
  6. ;--- 64bit:
  7. ;--- jwasm -win64 -Zp8 -I\WinInc\Include WinXX_1.asm
  8. ;--- link /subsystem:console /Libpath:\WinInc\Lib64 WinXX_1.obj
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-4-21 21:12:15 | 显示全部楼层
我一直在思考一个问题,是否能在32位模式下使用64位寄存器和一些64位指令。比如,在32位模式下,计算2个__int64的整数的和很费时,不得不使用adc指令,而使用64为寄存器和64位算术指令可以很快算出结果。 我尝试使用JWasm编译一个汇编文件,不使用win64参数,但是Jwasm总报错。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-4-21 21:14:54 | 显示全部楼层
不是能否使用emit 绕开汇编器的限制。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-4-21 21:39:11 | 显示全部楼层
我一直在思考一个问题,是否能在32位模式下使用64位寄存器和一些64位指令。比如,在32位模式下,计算2个__int64的整数的和很费时,不得不使用adc指令,而使用64为寄存器和64位算术指令可以很快算出结果。 我尝试使 ... liangbch 发表于 2011-4-21 21:12
也许可以尝试用 MMX 寄存器?(用 SSE2 指令 PADDQ)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-4-21 22:33:41 | 显示全部楼层
尝试使用 emit 绕开编译器限制,在32位模式下使用64bit 指令。 编译成功。运行也不出现异常,但是结果不对。不知是我的指令写的有问题,还是确实在32位模式下不能运行64位指令。
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. void arrayAdd_c(__int64 *p1, __int64 *p2)
  4. {
  5. *p1 += *p2;
  6. }
  7. _declspec(naked)
  8. void arrayAdd_asm( __int64 *p1, __int64 *p2)
  9. {
  10. __asm
  11. {
  12. push esi
  13. push edi
  14. mov edi, [esp+8+4]
  15. mov esi, [esp+8+8]
  16. mov eax,[edi]
  17. mov edx,[edi+4]
  18. add eax,[esi]
  19. adc edx,[esi+4]
  20. mov [edi],eax
  21. mov [edi+4],edx
  22. pop edi
  23. pop esi
  24. ret
  25. }
  26. }
  27. _declspec(naked)
  28. void arrayAdd_asm64( __int64 *p1, __int64 *p2)
  29. {
  30. __asm
  31. {
  32. push esi
  33. push edi
  34. mov edi, [esp+8+4]
  35. mov esi, [esp+8+8]
  36. //mov rax,qword ptr [edi]
  37. __asm _emit 0x67
  38. __asm _emit 0x48
  39. __asm _emit 0x8B
  40. __asm _emit 0x07
  41. //mov rdx,qword ptr [esi]
  42. __asm _emit 0x67
  43. __asm _emit 0x48
  44. __asm _emit 0x8B
  45. __asm _emit 0x16
  46. //add rax, rdx
  47. __asm _emit 0x48
  48. __asm _emit 0x03
  49. __asm _emit 0xC2
  50. //mov qword ptr [edi], rax
  51. __asm _emit 0x67
  52. __asm _emit 0x48
  53. __asm _emit 0x89
  54. __asm _emit 0x07
  55. /*
  56. movq mm0,qword ptr [edi]
  57. movq mm1,qword ptr [esi]
  58. paddq mm0, mm1
  59. movq qword ptr [edi], mm0
  60. */
  61. pop edi
  62. pop esi
  63. ret
  64. }
  65. }
  66. int main()
  67. {
  68. __int64 a1,a2,a3;
  69. __int64 b1,b2,b3;
  70. a1=a2=a3=12345678987654321I64;
  71. b1=b2=b3=5000000000I64;
  72. printf("a1=%I64d,a2=%I64d,a3=%I64d\n",a1,a2,a3);
  73. arrayAdd_c(&a1,&b1);
  74. arrayAdd_asm(&a2,&b2);
  75. arrayAdd_asm64(&a3,&b3);
  76. printf("a1=%I64d,a2=%I64d,a3=%I64d\n",a1,a2,a3);
  77. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-4-21 22:35:10 | 显示全部楼层
贴出运行结果,可以看到a3的值不对,说明arrayAdd_asm64工作不正常。
  1. a1=12345678987654321,a2=12345678987654321,a3=12345678987654321
  2. a1=12345683987654321,a2=12345683987654321,a3=12345679692687022
  3. 请按任意键继续. . .
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-4-21 22:36:07 | 显示全部楼层
在 函数 arrayAdd_asm64中,注释掉64位指令,改用MMX指令,发现结果是正确的。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-4-22 00:31:41 | 显示全部楼层
15# liangbch 呵呵,想法很大胆,我想也有很多人想过。生成32可执行文件,至少PE格式已指明了32位,rax高位就对你透明了。如果32位中用部分64寄存器和指令,我猜要切换模式,可能会有一些特权指令,ring3下也用不了,可什么时候切换呢?暂时没找到这样的例子,只好想象一下32位与64位的程序在时间片轮转中的情形。 以上都是个人猜测。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-4-27 15:12:11 | 显示全部楼层
JWasm的16/32/64是集成的,考虑到MS 的ml.exe 和ml64.exe 仍然可统一win32/win64编程. 调用规则上,win32多样,而win64只有fastcall (JWasm也如此)。所以为了调用的外观上一致,写了一个调用宏_invoke ,解决了这个问题。在编译和链接的时候,它们各自调用自己的include 和lib文件,源代码是共用的,干净凝练。 相关说明在代码中。 src.rar (3.27 KB, 下载次数: 1)
  1. ;---------------------------------------------------------------
  2. ;---------------------------------------------------------------
  3. ;--- Win32/Win64 simple GUI application. By G-Spider 2011
  4. ;--- Note: requires ml.exe \ml64.exe ,link.exe
  5. ;---------------------------------------------------------------
  6. ;--- X86
  7. ;--- ml /c /coff file.ASM
  8. ;--- link /out:win32.exe /subsystem:windows /entry:main file.obj
  9. ;---------------------------------------------------------------
  10. ;--- X64
  11. ;--- ml64 /c /Zp8 /D _WIN64=1 file.ASM
  12. ;--- link /out:win64.exe /subsystem:windows /entry:main file.obj
  13. ;---------------------------------------------------------------
  14. ;---------------------------------------------------------------
  15. ;说明:ml.exe 和ml64.exe中有个命令选项:
  16. ;/D sysmbol=value 定义给定名字的文本宏。
  17. ;所以可以通过这个命令来自动选择源代码中的x86或x64部分.
  18. ;在x86中,默认不用设置/D sysmbol=value或设置/D _WIN64=0
  19. ;若选择ml64.exe编译,可以加上/D _WIN64=1即可
  20. ;/Zp[n] 对结构指定的字节边界对齐
  21. ;---------------------------------------------------------------
  22. ifndef _WIN64
  23. _WIN64 equ <0>
  24. endif
  25. if _WIN64 eq 0 ;no -_WIN64 switch?
  26. .386
  27. .model flat, stdcall
  28. rax equ <eax>
  29. rbx equ <ebx>
  30. rcx equ <ecx>
  31. rdx equ <edx>
  32. rsp equ <esp>
  33. rbp equ <ebp>
  34. rsi equ <esi>
  35. rdi equ <edi>
  36. ;//如果x64的inc文件也合法的话,可以通用include ,只是路径不一样
  37. ;//一个是masm32\include 一个是masm64\include
  38. include user32.inc
  39. include kernel32.inc
  40. else ;_WIN64不为0 开启64位
  41. ;//X64的inc文件可以写成如下形式
  42. ;//用晓风残月的生成def/inc64工具即可
  43. extrn wsprintfA : proc
  44. extrn MessageBoxA : proc
  45. extrn ExitProcess : proc
  46. ;//
  47. endif
  48. option casemap:none
  49. includelib kernel32.lib
  50. includelib user32.lib
  51. ;================================================
  52. ;以下为通用调用宏
  53. ;================================================
  54. ;------------------------------------------------
  55. ; 参数翻转
  56. ;------------------------------------------------
  57. reverseArgs macro arglist:VARARG
  58. local txt,count
  59. txt TEXTEQU <>
  60. count = 0
  61. for i, <arglist>
  62. count=count+1
  63. txt TEXTEQU @CatStr(i, <,> , <%txt> )
  64. endm
  65. if count GT 0
  66. txt SUBSTR txt,1,@SizeStr(%txt)-1
  67. endif
  68. exitm txt
  69. endm
  70. ;------------------------------------------------
  71. ; 一个x86\x64 invoke Macro
  72. ;------------------------------------------------
  73. _invoke macro _Proc,args:VARARG
  74. local count
  75. local stack
  76. local rspL
  77. count= 0
  78. if _WIN64 NE 0 ;//不等于0时,选择X64,fastcall
  79. rspL = 20h
  80. % for i,<args>
  81. count=count+1
  82. if count GT 4
  83. rspL= rspL + 8h
  84. endif
  85. endm
  86. count=rspL/16
  87. count=count*16
  88. if rspL EQ count
  89. rspL=rspL+8
  90. endif
  91. sub rsp,rspL
  92. count = 0
  93. stack = 0
  94. % for i,<args>
  95. count = count + 1
  96. if count EQ 1
  97. mov rcx,i
  98. elseif count EQ 2
  99. mov rdx,i
  100. elseif count EQ 3
  101. mov r8,i
  102. elseif count EQ 4
  103. mov r9,i
  104. elseif count GE 5
  105. mov rax,i
  106. mov qword ptr [rsp+stack],rax
  107. endif
  108. stack = stack + 8
  109. endm
  110. call [_Proc]
  111. add rsp,rspL
  112. else
  113. % for i,< reverseArgs( args ) >
  114. count = count + 1
  115. push i
  116. endm
  117. call [_Proc]
  118. endif
  119. endm
  120. ;================================================
  121. ;以上为通用调用宏
  122. ;================================================
  123. .data
  124. imsg byte 'this invoke feels like 32bit',0
  125. szFmt1 byte '%d',0
  126. szFmt2 byte '%d %d',0
  127. szFmt3 byte '%d %d %d',0
  128. szFmt4 byte '%d %d %d %d ',0
  129. .data?
  130. Buffer dword 8 dup(?)
  131. .code
  132. main proc
  133. ;========================
  134. _invoke wsprintfA,offset Buffer,offset szFmt1,10h
  135. _invoke wsprintfA,offset Buffer,offset szFmt2,10h,16h
  136. _invoke wsprintfA,offset Buffer,offset szFmt3,10h,16h,17h
  137. _invoke wsprintfA,offset Buffer,offset szFmt4,10h,16h,17h,18h
  138. ;========================
  139. _invoke MessageBoxA,0,offset imsg,offset Buffer,0
  140. _invoke ExitProcess,0
  141. main endp
  142. end
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-4-27 19:45:25 | 显示全部楼层
我只进行过嵌入式汇编,对楼上的独立的asm文件操作不熟悉。 据说64位下VC不支持内嵌汇编(消息可靠否),不知Intel的编译器是否还支持?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-21 20:44 , Processed in 0.026073 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表