为什么要编写Win32汇编程序,直接C不好么?这种问题不想做过多的解释。
我只想写写我在编写这些汇编程序时遇到的困难,并且告诉大家我是怎么解决的,或许并不高明,但成功执行就是硬道理。
下面从一个简单的问题开始。
有时候我们会遇到一个像这样的接口函数:
int (*GetOutputTime)(); // 获取当前时间,以毫秒为单位。
而我们想要的是一个时、分、秒格式的输出,这样必然要进行转换。
反正我对计算不太敏感,特别是涉及到FPU指令集。怎么办呢?这时想到了用C实现,再反汇编,可以得到我们所需要的核心计算代码。
于是我编写了一个毫秒输入,时、分、秒输出的函数如下:
在VC6.0上编译得到以下重要汇编如下:
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; 13 : /*时、分、秒计算公式,重点看此处的反汇编*/
; 14 : lpPosition->hor=ps/3600000;
mov eax, DWORD PTR _ps$[ebp]
cdq
mov ecx, 3600000 ; 0036ee80H
idiv ecx
mov edx, DWORD PTR _lpPosition$[ebp]
mov DWORD PTR [edx], eax
; 15 : lpPosition->min=(ps/60000)%60;
mov eax, DWORD PTR _ps$[ ebp]
cdq
mov ecx, 60000 ; 0000ea60H
idiv ecx
cdq
mov ecx, 60 ; 0000003cH
idiv ecx
mov eax, DWORD PTR _lpPosition$[ ebp]
mov DWORD PTR [ eax+4], edx
; 16 : lpPosition->sec=((ps/1000)%60)%60;
mov eax, DWORD PTR _ps$[ ebp]
cdq
mov ecx, 1000 ; 000003e8H
idiv ecx
cdq
mov ecx, 60 ; 0000003cH
idiv ecx
mov eax, edx
cdq
mov ecx, 60 ; 0000003cH
idiv ecx
mov eax, DWORD PTR _lpPosition$[ ebp]
mov DWORD PTR [ eax+8], edx
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
到此我们所棘手的计算公式解决了,只要对上面的汇编稍加修改即可。
在此写出上面C对应的汇编,或者说实现上面接口功能的汇编程序已经不是问题了,对应的完整汇编如下:
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.386
.model flat,stdcall
option casemap:none
includelib msvcrt.lib
; CD Time structure
CDPOSITION STRUCT
Hour dd ?
Minute dd ?
Second dd ?
CDPOSITION ENDS
printf proto c:dword,:vararg
scanf proto c:dword,:vararg
GetPositionFromMusicTime proto :dword,:dword
.data
szFmt byte 'Ps=%d ',0Dh,0Ah,'Hour=%d ,Minute=%d, Second=%d',0,0,0,0
szF byte '%d',0
.data?
ps dd ?
TempPos CDPOSITION <?>
.code
;*********************************************
;计算时间
;*********************************************
GetPositionFromMusicTime proc uses esi edi MusicTime:DWORD,lpPosition:DWORD
mov edi, lpPosition
assume edi:ptr CDPOSITION
; hor=ps/3600000;
mov eax, MusicTime ;MusicTime以微秒为单位
cdq
mov ecx, 3600000
idiv ecx
mov [edi].Hour, eax
; min=(ps/60000)%60;
mov eax, MusicTime
cdq
mov ecx, 60000
idiv ecx
cdq
mov ecx, 60
idiv ecx
mov [edi].Minute, edx
; sec=((ps/1000)%60)%60;
mov eax, MusicTime
cdq
mov ecx, 1000
idiv ecx
cdq
mov ecx, 60
idiv ecx
mov eax, edx
cdq
mov ecx, 60
idiv ecx
mov [edi].Second, edx
xor eax,eax
ret
GetPositionFromMusicTime endp
start:
mov ps,65230000
mov TempPos.Second,0 ;初始化
mov TempPos.Minute,0
mov TempPos.Hour,0
invoke GetPositionFromMusicTime,ps,ADDR TempPos
invoke printf,offset szFmt,ps,TempPos.Hour,TempPos.Minute,TempPos.Second
ret
end start
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
下面编写了一个批处理(保存为**.bat)来编译上面的汇编:
@echo off
set include=D:/masm32/include
set lib=D:/masm32/lib
set path=D:/masm32/bin;%path%
echo on
ml /c /coff my.asm
link /subsystem:console my.obj
del *.obj
pause
my.exe
pause
运行情况如下: