初探从C到Win32汇编之系列一

此系列仅为初学者在直接编写Win32汇编程序时提供一点思路。

为什么要编写Win32汇编程序,直接C不好么?这种问题不想做过多的解释。
我只想写写我在编写这些汇编程序时遇到的困难,并且告诉大家我是怎么解决的,或许并不高明,但成功执行就是硬道理。
下面从一个简单的问题开始。

有时候我们会遇到一个像这样的接口函数:  
int   (*GetOutputTime)(); //   获取当前时间,以毫秒为单位。
而我们想要的是一个时、分、秒格式的输出,这样必然要进行转换。
反正我对计算不太敏感,特别是涉及到FPU指令集。怎么办呢?这时想到了用C实现,再反汇编,可以得到我们所需要的核心计算代码。

于是我编写了一个毫秒输入,时、分、秒输出的函数如下:

在VC6.0上编译得到以下重要汇编如下:
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; 13   :     /*时、分、秒计算公式,重点看此处的反汇编*/

; 14   :     lpPosition->hor=ps/3600000;
    mov    eaxDWORD PTR _ps$[ebp]
    cdq
    mov    ecx, 3600000              ; 0036ee80H
    idiv      ecx
    mov    edxDWORD PTR _lpPosition$[ebp]
    mov    DWORD PTR [edx], eax


; 15   :     lpPosition->min=(ps/60000)%60;
     mov     eaxDWORD  PTR _ps$[ ebp]
     cdq
     mov     ecx, 60000                 ; 0000ea60H
     idiv      ecx
     cdq
     mov     ecx, 60                    ; 0000003cH
     idiv      ecx
     mov     eaxDWORD  PTR _lpPosition$[ ebp]
     mov     DWORD  PTR [ eax+4],  edx

; 16   :     lpPosition->sec=((ps/1000)%60)%60;
     mov     eaxDWORD  PTR _ps$[ ebp]
     cdq
     mov     ecx, 1000                  ; 000003e8H
     idiv      ecx
     cdq
     mov     ecx, 60                    ; 0000003cH
     idiv       ecx
     mov     eaxedx
     cdq
     mov     ecx, 60                    ; 0000003cH
     idiv      ecx
     mov     eaxDWORD  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    eaxedx
    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

运行情况如下:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值