G-Spider 发表于 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位的可执行文件。
形如编译命令:
;--- Win32/64 console application, uses WinInc v2+.
;--- It can be used to generate both Win32 and Win64 binaries:
;--- 32bit:
;---jwasm -coff -I\WinInc\Include WinXX_1.asm
;---link /subsystem:console /Libpath:\WinInc\Lib WinXX_1.obj
;--- 64bit:
;---jwasm -win64 -Zp8 -I\WinInc\Include WinXX_1.asm
;---link /subsystem:console /Libpath:\WinInc\Lib64 WinXX_1.obj

liangbch 发表于 2011-4-21 21:12:15

我一直在思考一个问题,是否能在32位模式下使用64位寄存器和一些64位指令。比如,在32位模式下,计算2个__int64的整数的和很费时,不得不使用adc指令,而使用64为寄存器和64位算术指令可以很快算出结果。
我尝试使用JWasm编译一个汇编文件,不使用win64参数,但是Jwasm总报错。

liangbch 发表于 2011-4-21 21:14:54

不是能否使用emit 绕开汇编器的限制。

gxqcn 发表于 2011-4-21 21:39:11

我一直在思考一个问题,是否能在32位模式下使用64位寄存器和一些64位指令。比如,在32位模式下,计算2个__int64的整数的和很费时,不得不使用adc指令,而使用64为寄存器和64位算术指令可以很快算出结果。
我尝试使 ...
liangbch 发表于 2011-4-21 21:12 http://bbs.emath.ac.cn/images/common/back.gif

也许可以尝试用 MMX 寄存器?(用 SSE2 指令 PADDQ)

liangbch 发表于 2011-4-21 22:33:41

尝试使用 emit 绕开编译器限制,在32位模式下使用64bit 指令。
编译成功。运行也不出现异常,但是结果不对。不知是我的指令写的有问题,还是确实在32位模式下不能运行64位指令。#include <stdlib.h>
#include <stdio.h>

void arrayAdd_c(__int64 *p1, __int64 *p2)
{
        *p1 += *p2;
}

_declspec(naked)
void arrayAdd_asm( __int64 *p1, __int64 *p2)
{
        __asm
        {
                push esi
                push edi
               
                movedi,
                movesi,

                moveax,
                movedx,
                addeax,
                adcedx,
                mov,eax
                mov,edx

       
                popedi
                popesi

                ret
        }
}

_declspec(naked)
void arrayAdd_asm64( __int64 *p1, __int64 *p2)
{
        __asm
        {
                push esi
                push edi
               
                movedi,
                movesi,

               
                //movrax,qword ptr
                __asm _emit 0x67
                __asm _emit 0x48
                __asm _emit 0x8B
                __asm _emit 0x07

                //movrdx,qword ptr
                __asm _emit 0x67
                __asm _emit 0x48
                __asm _emit 0x8B
                __asm _emit 0x16

                //addrax, rdx
                __asm _emit 0x48
                __asm _emit 0x03
                __asm _emit 0xC2

                //movqword ptr , rax
                __asm _emit 0x67
                __asm _emit 0x48
                __asm _emit 0x89
                __asm _emit 0x07
               
                /*
                movqmm0,qword ptr
                movqmm1,qword ptr
                paddq mm0, mm1
                movqqword ptr , mm0
                */
               
                popedi
                popesi

                ret
        }
}


int main()
{
        __int64 a1,a2,a3;
        __int64 b1,b2,b3;

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

        arrayAdd_c(&a1,&b1);
        arrayAdd_asm(&a2,&b2);
        arrayAdd_asm64(&a3,&b3);

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

}

liangbch 发表于 2011-4-21 22:35:10

贴出运行结果,可以看到a3的值不对,说明arrayAdd_asm64工作不正常。a1=12345678987654321,a2=12345678987654321,a3=12345678987654321
a1=12345683987654321,a2=12345683987654321,a3=12345679692687022
请按任意键继续. . .

liangbch 发表于 2011-4-21 22:36:07

在 函数 arrayAdd_asm64中,注释掉64位指令,改用MMX指令,发现结果是正确的。

G-Spider 发表于 2011-4-22 00:31:41

15# liangbch
呵呵,想法很大胆,我想也有很多人想过。生成32可执行文件,至少PE格式已指明了32位,rax高位就对你透明了。如果32位中用部分64寄存器和指令,我猜要切换模式,可能会有一些特权指令,ring3下也用不了,可什么时候切换呢?暂时没找到这样的例子,只好想象一下32位与64位的程序在时间片轮转中的情形。
以上都是个人猜测。

G-Spider 发表于 2011-4-27 15:12:11

JWasm的16/32/64是集成的,考虑到MS 的ml.exe 和ml64.exe 仍然可统一win32/win64编程.
调用规则上,win32多样,而win64只有fastcall (JWasm也如此)。所以为了调用的外观上一致,写了一个调用宏_invoke ,解决了这个问题。在编译和链接的时候,它们各自调用自己的include 和lib文件,源代码是共用的,干净凝练。
相关说明在代码中。
;---------------------------------------------------------------
;---------------------------------------------------------------
;--- Win32/Win64 simple GUI application. By G-Spider 2011
;--- Note: requires ml.exe \ml64.exe ,link.exe
;---------------------------------------------------------------
;--- X86
;--- ml /c /cofffile.ASM
;--- link/out:win32.exe /subsystem:windows /entry:main file.obj
;---------------------------------------------------------------
;--- X64
;--- ml64 /c/Zp8 /D _WIN64=1 file.ASM
;--- link /out:win64.exe /subsystem:windows /entry:main file.obj
;---------------------------------------------------------------
;---------------------------------------------------------------
;说明:ml.exe 和ml64.exe中有个命令选项:
;/D sysmbol=value 定义给定名字的文本宏。
;所以可以通过这个命令来自动选择源代码中的x86或x64部分.
;在x86中,默认不用设置/D sysmbol=value或设置/D _WIN64=0
;若选择ml64.exe编译,可以加上/D _WIN64=1即可
;/Zp 对结构指定的字节边界对齐
;---------------------------------------------------------------

ifndef _WIN64
_WIN64 equ <0>
endif


if _WIN64 eq 0        ;no -_WIN64 switch?
.386
        .model flat, stdcall
rax   equ <eax>
rbx   equ <ebx>
rcx   equ <ecx>
rdx   equ <edx>
rsp   equ <esp>
rbp   equ <ebp>
rsi   equ <esi>
rdi   equ <edi>
;//如果x64的inc文件也合法的话,可以通用include ,只是路径不一样
;//一个是masm32\include 一个是masm64\include
        includeuser32.inc
        includekernel32.inc

else    ;_WIN64不为0 开启64位
;//X64的inc文件可以写成如下形式
;//用晓风残月的生成def/inc64工具即可
extrn        wsprintfA   : proc
extrn        MessageBoxA : proc
extrn        ExitProcess : proc
;//
endif

        option casemap:none

        includelib kernel32.lib
        includelib user32.lib
;================================================
;以下为通用调用宏
;================================================
;------------------------------------------------
; 参数翻转
;------------------------------------------------
reverseArgs macro arglist:VARARG
local txt,count
         
txt TEXTEQU <>
count = 0
for i, <arglist>
      count=count+1
      txt TEXTEQU   @CatStr(i, <,> , <%txt> )
endm
if count   GT   0
   txt SUBSTR   txt,1,@SizeStr(%txt)-1
endif
exitm txt
endm

;------------------------------------------------
; 一个x86\x64 invoke Macro
;------------------------------------------------
_invoke      macro   _Proc,args:VARARG
                local   count
                local   stack
                local   rspL

count= 0
if_WIN64    NE 0;//不等于0时,选择X64,fastcall
      rspL = 20h         
      %   for    i,<args>
               count=count+1
               if count GT 4
                     rspL= rspL + 8h
               endif
          endm
          count=rspL/16
          count=count*16
          if rspL EQ count
            rspL=rspL+8
          endif
      
          sub rsp,rspL
      
          count   = 0
          stack   = 0
      %   for   i,<args>                        
                  count= count + 1
                  if count EQ 1
                         mov rcx,i
                  elseif count EQ 2
                         mov rdx,i
                  elseif count EQ 3
                         mov r8,i
                  elseif count EQ 4
                         mov r9,i
                  elseif count GE 5
                         mov rax,i
                         mov qword ptr ,rax
                  endif
                  stack = stack + 8
          endm
          call   
          add rsp,rspL
else
      %   for i,< reverseArgs( args ) >
          count = count + 1
          push i
      endm
      call       
endif

endm
;================================================
;以上为通用调用宏
;================================================

.data
imsg   byte 'this invoke feels like 32bit',0
szFmt1 byte '%d',0
szFmt2 byte '%d %d',0
szFmt3 byte '%d %d %d',0
szFmt4 byte '%d %d %d %d ',0
.data?
Buffer dword 8 dup(?)

.code
main proc
;========================
_invoke wsprintfA,offset Buffer,offset szFmt1,10h
_invoke wsprintfA,offset Buffer,offset szFmt2,10h,16h
_invoke wsprintfA,offset Buffer,offset szFmt3,10h,16h,17h
_invoke wsprintfA,offset Buffer,offset szFmt4,10h,16h,17h,18h

;========================
_invoke MessageBoxA,0,offset imsg,offset Buffer,0
_invoke ExitProcess,0

main endp
        end

gxqcn 发表于 2011-4-27 19:45:25

我只进行过嵌入式汇编,对楼上的独立的asm文件操作不熟悉。
据说64位下VC不支持内嵌汇编(消息可靠否),不知Intel的编译器是否还支持?
页: 1 [2] 3
查看完整版本: 用vc2008开发64位程序,懂的请进