数学研发论坛

 找回密码
 欢迎注册
楼主: 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.                
  15.                 mov  edi, [esp+8+4]
  16.                 mov  esi, [esp+8+8]

  17.                 mov  eax,[edi]
  18.                 mov  edx,[edi+4]
  19.                 add  eax,[esi]
  20.                 adc  edx,[esi+4]
  21.                 mov  [edi],eax
  22.                 mov  [edi+4],edx

  23.        
  24.                 pop  edi
  25.                 pop  esi

  26.                 ret
  27.         }
  28. }

  29. _declspec(naked)
  30. void arrayAdd_asm64( __int64 *p1, __int64 *p2)
  31. {
  32.         __asm
  33.         {
  34.                 push esi
  35.                 push edi
  36.                
  37.                 mov  edi, [esp+8+4]
  38.                 mov  esi, [esp+8+8]

  39.                
  40.                 //mov  rax,qword ptr [edi]
  41.                 __asm _emit 0x67
  42.                 __asm _emit 0x48
  43.                 __asm _emit 0x8B
  44.                 __asm _emit 0x07

  45.                 //mov  rdx,qword ptr [esi]
  46.                 __asm _emit 0x67
  47.                 __asm _emit 0x48
  48.                 __asm _emit 0x8B
  49.                 __asm _emit 0x16

  50.                 //add  rax, rdx
  51.                 __asm _emit 0x48
  52.                 __asm _emit 0x03
  53.                 __asm _emit 0xC2

  54.                 //mov  qword ptr [edi], rax
  55.                 __asm _emit 0x67
  56.                 __asm _emit 0x48
  57.                 __asm _emit 0x89
  58.                 __asm _emit 0x07
  59.                
  60.                 /*
  61.                 movq  mm0,qword ptr [edi]
  62.                 movq  mm1,qword ptr [esi]
  63.                 paddq mm0, mm1
  64.                 movq  qword ptr [edi], mm0
  65.                 */
  66.                
  67.                 pop  edi
  68.                 pop  esi

  69.                 ret
  70.         }
  71. }


  72. int main()
  73. {
  74.         __int64 a1,a2,a3;
  75.         __int64 b1,b2,b3;

  76.         a1=a2=a3=12345678987654321I64;
  77.         b1=b2=b3=5000000000I64;
  78.        
  79.         printf("a1=%I64d,a2=%I64d,a3=%I64d\n",a1,a2,a3);

  80.         arrayAdd_c(&a1,&b1);
  81.         arrayAdd_asm(&a2,&b2);
  82.         arrayAdd_asm64(&a3,&b3);

  83.         printf("a1=%I64d,a2=%I64d,a3=%I64d\n",a1,a2,a3);

  84. }

复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 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)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-4-27 19:45:25 | 显示全部楼层
我只进行过嵌入式汇编,对楼上的独立的asm文件操作不熟悉。
据说64位下VC不支持内嵌汇编(消息可靠否),不知Intel的编译器是否还支持?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2022-6-28 21:21 , Processed in 0.074800 second(s), 17 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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