News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

I lose my time . Or CRT times functions

Started by ToutEnMasm, February 19, 2008, 02:22:31 PM

Previous topic - Next topic

ToutEnMasm

Hello,
Seeing than many peoples search for times functions, I see this in the CRT library:
http://www.warpspeed.com.au/cgi-bin/inf2html.cmd?..\html\book\IBMVACPP\CPPLIB.INF+24

17 functions not very hard to used,here is a sample:

Quote
   include C:\masm32\sdk\translate.inc
   include C:\masm32\sdk\stdio.sdk
   include C:\masm32\sdk\time.sdk
   includelib C:\PROGRA~1\MICROS~1.0\VC\lib\libcmt.lib   
   includelib C:\PROGRA~1\MICROS~1.0\VC\lib\OLDNAMES.lib
.data
format db "The time is %s",13,10,0
.code
main PROC C un:DWORD,deux:DWORD
   Local ltime:QWORD
   invoke time,addr ltime
   invoke ctime,addr ltime
   mov edx,eax
   invoke printf,addr format, edx
;****************************************************************************
;The output should be similar to:

;The time is Thu Jan 12 11:38:37 1995
;****************************************************************************/
   mov eax,0   
ret
main endp
end







Vortex

ToutEnMasm,

Using msvcrt.dll, the size of the executable is 1536 bytes :

.386
.model flat, stdcall
option casemap:none

include     \masm32\include\windows.inc
include     \masm32\include\msvcrt.inc
includelib  \masm32\lib\msvcrt.lib

.data
format db "The time is %s",13,10,0

.code

main PROC C un:DWORD,deux:DWORD
    LOCAL   ltime:QWORD
    invoke  crt_time,ADDR ltime
    invoke  crt_ctime,ADDR ltime
    invoke  crt_printf,ADDR format,eax
    xor     eax,eax
    ret
main ENDP
END

[attachment deleted by admin]

ToutEnMasm

Ok,the msvcrt.lib make many more little files,at the price of dependances with the .....80.dll.
With more code,a manifest is needed

Quote
;ressource
APP_MANIFEST RT_MANIFEST  DISCARDABLE  "Microsoft.VC80.CRT.manifest"
;-------------- content of file  Microsoft.VC80.CRT.manifest   in the directory of the project ------------
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation-->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
                                 manifestVersion="1.0">
  <noInheritable/>
  <assemblyIdentity
    type="win32"
    name="Microsoft.VC80.CRT"
    version="8.0.50608.0"
    processorArchitecture="x86"
    publicKeyToken="1fc8b3b9a1e18e3b" />
  <file name="msvcr80.dll"/>
  <file name="msvcp80.dll"/>
  <file name="msvcm80.dll"/>
</assembly>
;---------------------------------------------------------------------------------------------------------------------


Vortex

Hi ToutEnMasm,

You don't need the manifest file because the modified version of your example code above uses msvcrt.lib coming with the Masm32 package :

includelib  \masm32\lib\msvcrt.lib

I prefer to use Hutch's msvcrt.lib instead of another one supporting a higher version of Visual Studio.

GregL

Quote from: VortexI prefer to use Hutch's msvcrt.lib instead of another one supporting a higher version of Visual Studio.

Yes, I usually use the MASM32 version of msvcrt.lib (and ML and LINK) too.

If you want (have) to use some of the new "features" of Windows XP and Windows Vista, you are forced into using the newer ones.


ToutEnMasm


The masm lib have been modified and couldn't be mix with the other lib of the SDK,see:
http://www.masm32.com/board/index.php?topic=7996.msg58546#msg58546
That is for that I use the VC++ one.
When functions have a reserved name of masm,this can be solve by linking them dynamically.They are very few like that.
Duplicate name of functions (masm32 and sdk) can be solve by changing the name of the masm one.
I wait for a masm32 lib that is compatible with the SDK,not very difficult to do.


Vortex

ToutEnMasm,

Could you try this version of msvcrt.lib? It's another approach to solve the conflict with names.

GregL

Vortex,

Please explain how that msvcrt.lib is different from the one in the MASM32 package?


ToutEnMasm

Hello,
I have tested the msvcrt.ib of vortex (building the library and create the executable).
This one is build by link -lib option and extract from the dll.
It work.
For greg.
The new library is different in many things
-No entry point,the executable must provide one
-No need of manifest
-Functions are all renamed.
I don't see how link can do that but it made it.

I post a sample that use the normal way,that is VC++ libs.
The code is the one of vortex sample modify to use the vc++(2008) lib





[attachment deleted by admin]

ToutEnMasm


This demo is not completed without this third way ,the use of the libcmt.lib instead of msvcrt.lib.
Executable is bigger,there is no need of manifest,the code is exactly the same.
You win an executable who need less conditions to work.Try to run the one compiled with msvcrt in the zip,you have this message "..couldn't be initialised".He must be unpacked.
Try the same thing with this one.
The both samples I have posted,can be used with other libraries of the SDK.It isn't the case with the masm32 msvcrt.lib .
Explain:The msvcrt.lib give functions to other libraries in the SDK (ddk,directx,..)




[attachment deleted by admin]

Vortex

Hi ToutEnMasm,

Thanks for your examples. Would you like to try this new release? The previous version of msvcrt.lib did not contain the conflicting MASM keywords, I fixed it now. My apologies.

Hi Greg,

All the functions in the 2nd linker member table are prefixed with crt_ but all the IMAGE_ARCHIVE_MEMBER_HEADER entries are filled with original C function names so the prefixed names in the object files are "forwarded" to the conventional names by the linker.

GregL

Vortex,

Sorry if I am being thick, but I thought that's what the masm32 msvcrt.lib does, translates the crt_ prefixed function names to the actual function names.

I guess I have always taken import libraries for granted, is there any good documentation about the inner workings of them.



GregL

Vortex,

So, you are saying I need to do some reading?  :bg  Thanks for the link.


ToutEnMasm,

Regarding the CRT date and time functions, I posted an example here. After assembling and running it today, I found an error and updated it.


ToutEnMasm

Hi greg,
I have made a rewrite of your code using the windows.sdk
The only change is GetTimeZoneInformation instead of :
Quote
mov eax, crt__tzname
    .if tstruct.dstflag == 0
        mov edx, [eax+0] 
        mov ptzname, edx
    .else
The 'mov eax, crt__tzname' need a real explain and is deprecated.
Quote
invoke printf, chr$(" Days until Christmas:               %.0L",13,10), days

The format  %fl made a runtime error ,change to %.0L

That's all


Quote
    .486
    .model flat, stdcall
    option casemap :none
   include \masm32\sdk\translate.inc
   include \masm32\sdk\windows.sdk
   include \masm32\sdk\stdio.sdk
   include \masm32\sdk\conio.sdk
   include \masm32\sdk\time.sdk
   include \masm32\sdk\timeb.sdk   
   include \masm32\sdk\mapiwin.sdk
   
    includelib C:\PROGRA~1\MICROS~1.0\VC\lib\libcmt.lib   
    includelib C:\PROGRA~1\MICROS~1.0\VC\lib\oldnames.lib
   
    includelib c:\masm32\lib\kernel32.lib
   
    include macro.inc
           
    main PROTO C :DWORD,:DWORD
    maincrt PROTO
    _difftime64 PROTO pTime1:PTR QWORD, pTime2:PTR QWORD, pDiff:PTR REAL8
    WaitKeyCrt PROTO
.data

    align 8
    time1     QWORD     0
    time2     QWORD     0
    diff      REAL8     0.0
    day       REAL8     86400.0  ; 60*60*24
    days      REAL8     0.0
    tstruct   __timeb64 <0>
    align 4
    hmodule   DWORD     0
    pxmas     DWORD     0
    ptzname   DWORD     0
    tmpbuf    BYTE      128 dup(0)
    ampm      BYTE      "AM", 0
    newline   BYTE      13, 10, 0
    tziOld TIME_ZONE_INFORMATION <>
.code

main proc C un:DWORD,deux:DWORD
    invoke maincrt
    invoke WaitKeyCrt
ret
main endp

maincrt  PROC
   Local dwRet:DWORD
   Local timezone[64]:BYTE

    invoke _tzset
    invoke printf, chr$(13,10,"64-bit Date and Time Functions - C Run-time Library",13,10)
    invoke _strtime, ADDR tmpbuf
    invoke printf, chr$(" OS time:                            %s",13,10), ADDR tmpbuf
    invoke _strdate, ADDR tmpbuf
    invoke printf,chr$(" OS date:                            %s",13,10), ADDR tmpbuf
    invoke _time64, ADDR time1
    invoke printf, chr$(" Time in seconds since UTC 1/1/1970: %I64u",13,10), time1
    invoke _ctime64, ADDR time1
    invoke printf, chr$(" Time and date string:               %s"), eax
    invoke _gmtime64, ADDR time1
    invoke asctime, eax
    invoke printf, chr$(" Coordinated universal time:         %s"), eax
    invoke _localtime64, ADDR time1
    mov edx, (tm PTR [eax]).tm_hour
    .if edx >= 12
        push eax
        push edx
        invoke strcpy, ADDR ampm, chr$("PM")
        pop edx
        pop eax
        sub edx, 12
        mov (tm PTR [eax]).tm_hour, edx
    .endif 
    mov edx, (tm PTR [eax]).tm_hour
    .if edx == 0
        mov (tm PTR [eax]).tm_hour, 12
    .endif
    invoke asctime, eax
    add eax, 11
    invoke printf, chr$( " 12-hour time:                       %.8s %s",13,10), eax, ADDR ampm
    invoke _ftime64, ADDR tstruct
    movsx eax, tstruct.millitm 
    invoke printf, chr$(" Plus milliseconds:                  %u",13,10), eax
    xor edx, edx
    movsx eax, tstruct.timezone
    mov ecx, 60
    div ecx
    invoke printf, chr$(" Zone difference in hours from UTC:  %u",13,10), eax
     invoke GetTimeZoneInformation,addr tziOld
      .if eax == TIME_ZONE_ID_STANDARD
         lea edx,tziOld.StandardName   
         invoke WideCharToMultiByte,CP_ACP,WC_COMPOSITECHECK,edx,\
            -1,addr timezone,sizeof timezone,NULL,NULL
         lea edx,timezone
               
      .elseif eax == TIME_ZONE_ID_DAYLIGHT
         lea edx,tziOld.DaylightName   
         invoke WideCharToMultiByte,CP_ACP,WC_COMPOSITECHECK,edx,\
            -1,addr timezone,sizeof timezone,NULL,NULL
         lea edx,timezone               
      .else
         mov edx,chr$("GTZI failed ")
      .endif
   mov     ptzname,edx         
    invoke printf, chr$(" Time zone name:                     %s",13,10), ptzname

        invoke printf, chr$( " Daylight savings:                   ")
    movsx eax, tstruct.dstflag
    .if eax == 0
        invoke printf, chr$("False",13,10)
    .else
        invoke printf, chr$("True",13,10)
    .endif
    invoke _localtime64, ADDR time1
    invoke strftime, ADDR tmpbuf, SIZEOF tmpbuf, chr$("%A, %B %d, %Y"), eax
    invoke printf, chr$(" Today is:                           %s",13,10), ADDR tmpbuf
    invoke _localtime64, ADDR time1
    mov edx, 11                     ; December
    mov (tm PTR [eax]).tm_mon, edx
    mov edx, 25                     ; 25th
    mov (tm PTR [eax]).tm_mday, edx
    mov edx, 12                     ; 12:00 noon   
    mov (tm PTR [eax]).tm_hour, edx
    mov edx, 0
    mov (tm PTR [eax]).tm_min, edx
    mov edx, 0
    mov (tm PTR [eax]).tm_sec, edx
    mov edx, 0
    mov (tm PTR [eax]).tm_wday, edx
    mov edx, 0
    mov (tm PTR [eax]).tm_yday, edx
    mov edx, 0
    mov (tm PTR [eax]).tm_isdst, edx
    mov pxmas, eax
    invoke _mktime64, eax
    mov DWORD PTR [time2+0], eax
    mov DWORD PTR [time2+4], edx
    .if DWORD PTR eax != -1 && DWORD PTR edx != -1
        invoke strftime, ADDR tmpbuf, SIZEOF tmpbuf, chr$("%A, %B %d, %Y"), pxmas
        invoke printf, chr$(" Christmas this year:                %s",13,10), ADDR tmpbuf
   .endif
    invoke _difftime64, ADDR time1, ADDR time2, ADDR diff
    finit
    fld diff
    fld day
    fdiv
    fstp days ;REAL8
   ;runtime error R6002 - floating point support not loaded fl
    invoke printf, chr$(" Days until Christmas:               %.0L",13,10), days
    ret
maincrt  ENDP

_difftime64 PROC pTime1:PTR QWORD, pTime2:PTR QWORD, pDiff:PTR REAL8
    ; MS Visual C Run-time Library does not have a _difftime64 function so...
    mov     eax, pTime1
    mov     edx, pTime2
    finit                   ; initialize FPU
    ; compare Time1 with Time2
    fild    QWORD PTR [edx] ; st(0) = Time2
    fild    QWORD PTR [eax] ; st(0) = Time1, st(1) = Time2
    fcompp                  ; compare st(0) with st(1) and pop both registers
    fstsw   ax              ; retrieve comparison result in the AX register
    fwait                   ; insure the previous instruction is completed
    sahf                    ; transfer the condition codes to the CPU's flag register
    jb      st0_less        ; only the C0 bit (CF flag) would be set if no error
st0_greater:                ; Time1 > Time2
    ;Subtract Time2 from Time1 to calculate the number of seconds difference
    mov     eax, pTime1
    mov     edx, pTime2
    fild    QWORD PTR [eax]
    fild    QWORD PTR [edx]
    fsub
    mov     eax, pDiff
    fstp    REAL8 PTR [eax]
    fwait
    jmp     @F
st0_less:                  ; Time2 > Time1
    ;Subtract Time1 from Time2 to calculate the number of seconds difference
    mov     eax, pTime2
    mov     edx, pTime1
    fild    QWORD PTR [eax]
    fild    QWORD PTR [edx]
    fsub
    mov     eax, pDiff
    fstp    REAL8 PTR [eax]
    fwait
@@:
    ret
_difftime64 ENDP

WaitKeyCrt PROC
    invoke printf, chr$(13,10,"Press any key to continue...")
    invoke _getch
    .if (eax == 0) || (eax == 0E0h)
        invoke _getch
    .endif
    invoke printf, ADDR newline   
    ret
WaitKeyCrt ENDP

END