|
来源:http://www.x64asm.com/AsmBbs/viewthread.php?tid=413
作者:晓风残月
关于64位浮点参数传递一直停留在理论阶段,只知道资料上说是通过XMM0-XMM3这4个SSE寄存器传递,没有实际测试过,但是测试出来的结果却不一样,浮点参数仍然通过通用寄存器传递,有人会问什么了,整数寄存器怎么传递浮点参数,呵呵,听我慢慢解释(靠,谁扔的鸡蛋,用得着这么心急么)
浮点数分单精度,双精度和扩展精度,扩展精度不太常用,而且我也没研究出来怎么传递,暂不讨论。单精度浮点数数据长度为32位,双精度浮点数据长度为64位,同样可以定义为dword 和 qword,只是在内存中的表现形式和整数不一样,如果用mov指令则只能传送整数。传送浮点数到通用寄存器需要一定的技巧,这里需要使用到SSE指令集,先通过SSE寄存器把数据编码为浮点格式,然后通过SSE字节传送指令原封不动的把浮点编码格式的数据传递到通用寄存器。
在程序中用到2个SSE指令,MOVSD和MOVD:
MOVSD ( Move Scalar Double-Precision Floating-Point Value ) 传送标量双精度浮点值
指令格式:movsd dest, src
两个操作数可以是通用寄存器,SSE寄存器,和内存操作数,不支持立即数
MOVD ( Move Doubleword )传送双字节
指令格式:movd dest, src
两个操作数可以是通用寄存器,SSE寄存器和内存操作数,不支持立即数
下面我们来实际看下代码应用
- .data
- szdll byte "msvcrt.dll", 0
- szSprintf byte "sprintf", 0
- szcaption byte "test x64 float point past", 0
- szformat byte "test x64 float point past : %.3f, %.2f, %f", 0
- val1 qword 123.5432
- val2 qword 321.6543
- val3 qword 123456.9876
- .data?
- szbuffer byte 50 dup ( ? )
- .code
- main proc
- sub rsp, 38h
- lea rcx, szdll
- call GetModuleHandle
- mov rcx, rax
- lea rdx, szSprintf
- call GetProcAddress
- lea rcx, szbuffer
- lea rdx, szformat
- movsd xmm0, val1 ; 传送到SSE寄存器编码为浮点格式
- movd r8, xmm0 ; 双字节传送到通用寄存器
- movsd xmm0, val2
- movd r9, xmm0
- movsd xmm0, val3
- movd qword ptr [ rsp + 20h ], xmm0 ; 第5个参数是浮点参数也通过堆栈传递,因为堆栈是8字节的,所以要用qword ptr关键字指定操作大小,否则会按4字节传递,即movd dword ptr [ rsp + 20h ]
- call rax
- xor rcx, rcx
- lea rdx, szbuffer
- lea r8, szcaption
- xor r9, r9
- call MessageBox
- xor rax, rax
- jmp ExitProcess
- main endp
- end
复制代码
把此程序编译后就能看到结果了。 |
|