The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: theiod on May 01, 2006, 04:19:13 AM

Title: More GetLocalTime
Post by: theiod on May 01, 2006, 04:19:13 AM
I am an assembly newbie, and am having troubles getting my time formatted. As it stands now it keeps crashing somewhere inside my procedure to convert the time. Ollydebug hasn't helped. I'm working on getting the visual studio debugger to work now.

If any one can help me get the date and time formatted in this way I'd really appreciate the help.
I'm trying to use GetLocalTime to output the date and time in this format:

Sun, Apr 30, 2006
09:16:14 PM

I appreciate your help and time.

Thanks in advance.

Extreme Newbie
Title: Re: More GetLocalTime
Post by: asmGhost on May 01, 2006, 05:25:30 AM
Take a look at these 2 links.
GetDateFormat (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_5w6s.asp)
GetTimeFormat (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_5w6s.asp)
Title: Re: More GetLocalTime
Post by: Ossa on May 01, 2006, 09:04:57 AM
Here's a simple console example. It uses the date formats that you specified... note that I added CRLFs to the format string - if this is for a windows app, you will more than likely want to remove that. This will probably be what you want (instead of what I have):

szDFormat               db              "ddd',' MMM dd',' yyyy", 0
szTFormat               db              "hh':'mm':'ss tt", 0


If you have code already written, it might help to post it (just the relevent bits), as people can then give advice more suited to your problem.

Hope it helps,
Ossa

(As asmGhost pointed out, the reference will give details on how to modify this to do exactly what you like.)

; Include, etc

.386
.model FLAT, STDCALL
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib

; String lengths

MAX_DATE_LEN            EQU             20
MAX_TIME_LEN            EQU             15

; Format strings

.data

szDFormat               db              "ddd',' MMM dd',' yyyy'", 0Dh, 0Ah, "'", 0
szTFormat               db              "hh':'mm':'ss tt'", 0Dh, 0Ah, "'", 0

; Run time data

.data?

stCurTime               SYSTEMTIME      <>
szDate                  db              MAX_DATE_LEN dup (?)
szTime                  db              MAX_TIME_LEN dup (?)

; Start code

.code
start:

; Get time

invoke GetSystemTime, addr stCurTime

; Convert

invoke GetDateFormat, LOCALE_USER_DEFAULT, NULL, addr stCurTime, addr szDFormat, addr szDate, MAX_DATE_LEN
invoke GetTimeFormat, LOCALE_USER_DEFAULT, NULL, addr stCurTime, addr szTFormat, addr szTime, MAX_TIME_LEN

; Output

invoke StdOut, addr szDate
invoke StdOut, addr szTime

; Exit

invoke ExitProcess, 0

; End code

end start


[edit]

Oops... just re-read the OP. To use GetLocalTime (instead of GetSystemTime as I used), replace

invoke GetSystemTime, addr stCurTime

with

invoke GetLocalTime, addr stCurTime

[/edit]
Title: Re: More GetLocalTime
Post by: PBrennick on May 01, 2006, 11:12:00 AM
If you change ...

invoke GetDateFormat, LOCALE_USER_DEFAULT, NULL, addr stCurTime, addr szDFormat, addr szDate, MAX_DATE_LEN
invoke GetTimeFormat, LOCALE_USER_DEFAULT, NULL, addr stCurTime, addr szTFormat, addr szTime, MAX_TIME_LEN


to ...

invoke GetDateFormat, LOCALE_USER_DEFAULT, NULL, NULL, addr szDFormat, addr szDate, MAX_DATE_LEN
invoke GetTimeFormat, LOCALE_USER_DEFAULT, NULL, NULL, addr szTFormat, addr szTime, MAX_TIME_LEN


The time that is displayed in the console window will be formatted correctly according to your personal offset to GMT.

hth,
Paul


[attachment deleted by admin]
Title: Re: More GetLocalTime
Post by: Ossa on May 01, 2006, 11:25:55 AM
Indeed, a much simpler method if all you want is the current time. However, if you want to display something other than the current time, then you must include the pointer to the SYSTEMTIME structure. An example of this might be displaying file times using the GetFileTime and FileTimeToSystemTime functions... It all depends on what the desired application is.

Ossa
Title: Re: More GetLocalTime
Post by: PBrennick on May 01, 2006, 12:47:45 PM
Ossa,
You are right and it is important for someone who is learning to be aware of all the options.  I like your example as it is short and to the point which makes it a good learning example.  I have added it to my archives plus I have turned it into a project.

Paul
Title: Re: More GetLocalTime
Post by: theiod on May 01, 2006, 10:43:34 PM
I tried using the getdateformat and gettimeformat, but I'm using MASM615. I added PROTOs for them, but maybe I'm missing something. I get this error:

sTime.obj : error LNK2001: unresolved external symbol _GetDateFormat@24
sTime.obj : error LNK2001: unresolved external symbol _GetTimeFormat@24
sTime.exe : fatal error LNK1120: 2 unresolved externals

Any clues? Can I even use those libraries with masm 6.15?
Title: Re: More GetLocalTime
Post by: Ossa on May 01, 2006, 10:57:01 PM
I take that you are using PBrennick's file? You aren't linking the correct lib files correctly apparently. It should work fine with your version of MASM.

Try the one attached instead - just double click the .bat file once you've extracted the files (assuming that masm is installed in the default directory).

Ossa

[attachment deleted by admin]
Title: Re: More GetLocalTime
Post by: theiod on May 01, 2006, 11:43:43 PM
That worked when I ran the bat file.

I need to be able to make an exe though. Here is my make32.bat. When I try to assemble the program it dies. It doesn't know the include files. Infact I dont' have most of those seeing as I'm using MASM615 not MASM32

REM  make32.bat -  Custom batch file for assembling/linking the
REM  WinApp.asm program.
REM  Revised: 2/1/01

@echo off
cls

REM The following three lines can be customized for your system:
REM ********************************************BEGIN customize
PATH C:\Masm615
SET INCLUDE=C:\Masm615\include
SET LIB=C:\Masm615\lib
REM ********************************************END customize

ML -Zi -c -Fl -coff %1.asm
if errorlevel 1 goto terminate

REM add the /MAP option for a map file in the link command.

LINK32 %1.obj kernel32.lib user32.lib /SUBSYSTEM:WINDOWS
if errorLevel 1 goto terminate

dir %1.*

:terminate
pause
Title: Re: More GetLocalTime
Post by: theiod on May 01, 2006, 11:53:08 PM
Correction I was running another app. The bat file doesn't work either. I don't have a masm32 I have a masm615 folder.
Title: Re: More GetLocalTime
Post by: Ossa on May 02, 2006, 08:29:31 AM
In order to use any of the Windows API, you will need the correct includes that come with the MASM32 package (it still uses MASM 6.15, but just has all the related files that you will need). It IS possible to write all of the type/procedure definitions yourself, but it will be very annoying to do so. You will also need the .lib files - i think you can get these with some of the MS downloads.

I would recommend, however, that you just install MASM32.

Ossa
Title: Re: More GetLocalTime
Post by: PBrennick on May 02, 2006, 10:15:20 AM
theiod,
Download and install masm32.  After it is installed, make a backup of the bin directory.  Once you have done that, copy all the files from your masm615 folder into \masm32\bin

Once you have done that, your copy of my project will build (once you restore it to the way it was originally.  I use version 6.15 pf ml.exe, also.

Paul
Title: Re: More GetLocalTime
Post by: jckl on May 02, 2006, 10:47:02 AM
You could also craete a struct to format the date and time like so.
DATETIME struct
   dmo BYTE 2 dup(?)
       BYTE '/'
   dda BYTE 2 dup(?)
       BYTE '/'
   dyr BYTE 4 dup(?)
       BYTE ' '
   dhour BYTE 2 dup(?)
         BYTE ':'
   dmin BYTE 2 dup(?)
        BYTE ':'
   dsec BYTE 2 dup(?)
        BYTE 0
DATETIME ends




Also to turn system time into the correct time zone you can use the following code.
   invoke GetTimeZoneInformation, ADDR TZI
   mov eax, TZI.Bias
   imul eax, 60
   sub SecsPast, eax
   mov eax, TZI.DaylightBias
   imul eax, 60
   sub SecsPast, eax
Title: Re: More GetLocalTime
Post by: Mark Jones on May 02, 2006, 09:08:07 PM
Also Theiod, don't be confused by 16-bit and 32-bit code. 16-bit code is old DOS .com and .exe files. The MASM32 package will build 32-bit Windows code natively, which will not run in DOS. To build DOS code, MASM v6.15 can be used but you must use a 16-bit LINK.EXE. Just F.Y.I. :U
Title: Re: More GetLocalTime
Post by: theiod on May 04, 2006, 02:45:10 AM
Reply to Mark Jones:
I've written about a dozen 32-bit masm 6.15 programs that run in DOS.

Is there something else you are talking about?


Reply to all:
By the way I got MASM32 to work and that resolved it. Unfortunately I couldn't ever find a way to do it in straight MASM 6.15 code.

I really appreciate all your help. You guys are awesome.
Title: Re: More GetLocalTime
Post by: Synfire on May 04, 2006, 03:22:37 AM
theiod,

Don't confuse the console with the DOS operating system. Mark Jones was explaining that the old DOS/COM and MZ/EXE are 16-BIT code whereas Windows PE/EXE code is 32-BIT. The DOS operating system (unless maybe FreeDOS or some other newer versions) are almost always 16-BIT real mode operating systems and run 16-BIT executables. On Windows the "DOS" box you get is a console window which, on versions after Win98 (iirc), simply emulates the old DOS command line. There is a LINK.EXE which builds 16-BIT DOS/COM and MZ/EXE programs and he was mearly turning you on to this.

As for not using MASM32, is there a reason that you don't wish to use it? You can create windows applications without MASM32 but it makes things a lot easier, and as you mentioned you are "an assembly newbie". I'm personally not sure how to build Win32 Applications without using the PlatformSDK (if there is a way), in nasm it's very easy as my NASM32 package basically encapsulates this method to keep the download size down. If you look in the \MASM32\Examples\exampl08\masm1k directory you can see how to build applications using the import libraries alone (which doesn't require MASM32 but does require you to have a copy of the PlatformSDK). I did create a include file called K32BINC which can still be downloaded off of http://www.codegurus.org/~bkeller under the projects tab, but be forewarned that this method creates executables without an import section and on Win2K the PE Loader refuses to run any application that doesn't have an import section (on Win2K you have to at least have kernel32.dll loaded) so this isn't a really good method to develop anything you plan to release. I'm sure Hutch or one of the others could point you into a better method but I honestly don't use MASM a whole lot.

Regards,
Bryant Keller
Title: Re: More GetLocalTime
Post by: hutch-- on May 04, 2006, 04:06:34 AM
theiod,

Bryant is correct here, a package that puts many things to gether for you is a far better proposition that trying to nut all of this stuff out the hard way. Most of the older programmers can write applications in most of the available assembler and can write them in bare mnemonics but its a very hard road to start with so its not really recommended.

The version of ML you are using ML.EXE 6.15 is a very good version that you can simply place in the MASM32 BIN directory instead of the 6.14 version that is there at the moment and it will work fine for you.

Once you are familiar enough with 32 bit assembler instructions and windows architecture and API calls, its no big deal to work in other assembler and some of them are very good. I personally like POASM and GAS but NASM is very well respected, FASM has a big following and GoAsm is a very well written tool with classy accessories. Once you are up and going properly, you can write what you like in whatever tool you like.
Title: Re: More GetLocalTime
Post by: MichaelW on May 04, 2006, 10:10:36 AM
theiod,

Starting with the source that Ossa posted, this shows how to do it in straight MASM code, without any libraries (import or static) or includes. AFAIK the Microsoft linker is dependent on libraries, so I used GoLink (http://www.jorgon.freeserve.co.uk/) to perform the linking step.


; test.asm

.386
.model FLAT, STDCALL
option casemap:none

; Necessary structure definition

SYSTEMTIME STRUCT
  wYear             WORD      ?
  wMonth            WORD      ?
  wDayOfWeek        WORD      ?
  wDay              WORD      ?
  wHour             WORD      ?
  wMinute           WORD      ?
  wSecond           WORD      ?
  wMilliseconds     WORD      ?
SYSTEMTIME ENDS

; Necessary equates

NULL equ 0
LOCALE_USER_DEFAULT equ 0400h
STD_OUTPUT_HANDLE equ -11

; Prototypes for the called kernel32.dll functions

GetLocalTime PROTO :DWORD
GetDateFormatA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
GetDateFormat equ GetDateFormatA
GetTimeFormatA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
GetTimeFormat equ GetTimeFormatA
GetStdHandle PROTO :DWORD
WriteFile PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ExitProcess PROTO :DWORD

; Prototypes for the included MASM32 library procedures

StdOut PROTO :DWORD
StrLen PROTO :DWORD

; String lengths

MAX_DATE_LEN EQU 20
MAX_TIME_LEN EQU 15

; Format strings

.data

  szDFormat db "ddd',' MMM dd',' yyyy'", 0Dh, 0Ah, "'", 0
  szTFormat db "hh':'mm':'ss tt'", 0Dh, 0Ah, "'", 0
 
  szDateTitle db "Date", 0
  szTimeTitle db "Time", 0

; Run time data

.data?

  stCurTime SYSTEMTIME <>
  szDate db MAX_DATE_LEN dup (?)
  szTime db MAX_TIME_LEN dup (?)

; Start code

.code
start:

    ; Get time
   
    invoke GetLocalTime, addr stCurTime

    ; Convert

    invoke GetDateFormat, LOCALE_USER_DEFAULT, NULL, addr stCurTime, addr szDFormat, addr szDate, MAX_DATE_LEN
    invoke GetTimeFormat, LOCALE_USER_DEFAULT, NULL, addr stCurTime, addr szTFormat, addr szTime, MAX_TIME_LEN

    ; Output

    invoke StdOut, addr szDate
    invoke StdOut, addr szTime

    ; Exit

    invoke ExitProcess, 0

; ---------------------------------------------------
; These are copies of the MASM32 library procedures.
; ---------------------------------------------------

StdOut proc lpszText:DWORD

    LOCAL hOutPut  :DWORD
    LOCAL bWritten :DWORD
    LOCAL sl       :DWORD

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov hOutPut, eax

    invoke StrLen,lpszText
    mov sl, eax

    invoke WriteFile,hOutPut,lpszText,sl,ADDR bWritten,NULL

    mov eax, bWritten
    ret

StdOut endp

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

align 4

StrLen proc item:DWORD

  ; -------------------------------------------------------------
  ; This procedure has been adapted from an algorithm written by
  ; Agner Fog. It has the unusual characteristic of reading up to
  ; three bytes past the end of the buffer as it uses DWORD size
  ; reads. It is measurably faster than a classic byte scanner on
  ; large linear reads and has its place where linear read speeds
  ; are important.
  ; -------------------------------------------------------------

    mov     eax,[esp+4]             ; get pointer to string
    push    ebx
    lea     edx,[eax+3]             ; pointer+3 used in the end
  @@:     
    mov     ebx,[eax]               ; read first 4 bytes
    add     eax, 4                  ; increment pointer
    lea     ecx,[ebx-01010101h]     ; subtract 1 from each byte
    not     ebx                     ; invert all bytes
    and     ecx,ebx                 ; and these two
    and     ecx, 80808080h
    jz      @B                      ; no zero bytes, continue loop

    test    ecx,00008080h           ; test first two bytes
    jnz     @F
    shr     ecx,16                  ; not in the first 2 bytes
    add     eax,2
  @@:
    shl     cl,1                    ; use carry flag to avoid branch
    sbb     eax,edx                 ; compute length
    pop     ebx

    ret     4

StrLen endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

; End code

end start


And a batch file to assemble, link and test it:

if exist test.obj del test.obj
if exist test.exe del test.exe
ml /c /coff test.asm
pause
GoLink /console test.obj kernel32.dll user32.dll
pause
test
pause


For this small simple app the source file more than tripled in size (3878 bytes versus 1024 bytes). Had I not been able to get the necessary definitions and prototypes from the MASM32 include and source files I would have had to spend a significant amount of time searching through documentation and header files, and writing and testing support code.


Title: Re: More GetLocalTime
Post by: theiod on May 04, 2006, 04:26:15 PM
The only reason I needed to use straight masm 615 was that this one was part of a design requirement. This time I was able to talk my way out of it, but we'll see if  it continues that way.

You guys are right, I've been in windows too long I keep forgetting the difference between the console, and DOS.

Title: Re: More GetLocalTime
Post by: Mark Jones on May 04, 2006, 05:54:49 PM
Quote from: theiod on May 04, 2006, 02:45:10 AM
I've written about a dozen 32-bit masm 6.15 programs that run in DOS.

Is there something else you are talking about?

Well apparently I'm confused. As long as you understand... :lol