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
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)
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]
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]
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
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
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?
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]
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
Correction I was running another app. The bat file doesn't work either. I don't have a masm32 I have a masm615 folder.
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
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
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
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
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.
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
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.
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.
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.
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