Hi all, I'm new to this forum and sorry for my bad English.
In this simple code:
include masm32rt.inc
.data?
SysTime SYSTEMTIME <?>
.data
.code
start:
invoke GetSystemTime, addr SysTime
printf("%d\n", SysTime.wYear);
inkey "Press a key to continue ..."
invoke ExitProcess, NULL
end start
An error in printf, I'm pretty sure it's because they do not get the correct type for SysTime.wYear (word).
I tried various combinations (%d,%i, etc ...), but not how to fix it. Would be grateful if anyone of you tell me how to fix the runtime error.
the problem is probably, that wYear is a WORD, which cause the invoke macro to produce bad code -> move the value to a 32Bit GPR and then pass it to the macro:
movzx edx,SysTime.wYear
printf(...,edx)
What exactly is your problem? This code assembles and runs fine. Below the printf macro.
include \masm32\include\masm32rt.inc
.data
SysTime SYSTEMTIME <>
.code
start:
mov ebx, esp
invoke GetSystemTime, addr SysTime
printf("%d\n\n", SysTime.wYear);
sub ebx, esp
inkey str$(ebx), 9, "StackDiff"
exit
end start
\masm32\macros\macros.asm
; --------------------------------------------------------------
; This macro is written to behave as closely as possible to the
; C runtime function "printf". The lack of return value is
; to allow the closest method to writing C code. It supports
; both ASCII and UNICODE and uses the C runtime function
; "wprintf" to provide the UNICODE support.
;
; printf("%d\t%d\t%Xh\n", 123, 456, 1024);
;
; The return value is available in the EAX register if required.
; The original ASCII version was written by Michael Webster.
; --------------------------------------------------------------
printf MACRO format:REQ, args:VARARG
IFNDEF __UNICODE__
IFNB <args>
fn crt_printf, cfm$(format), args
ELSE
fn crt_printf, cfm$(format)
ENDIF
EXITM <>
ELSE
IFNB <args>
fn crt_wprintf, cfm$(format), args
ELSE
fn crt_wprintf, cfm$(format)
ENDIF
EXITM <>
ENDIF
ENDM
(http://image-upload.de/image/p5SZLn/dea021d156.png)
OK. Seems the macro needs an update ::)
I didn't see a problem because my default assembler is JWasm. The code crashes with ML 6.14...8.0 but assembles fine with ML 9.0 and JWasm ().
0040100D ³. 66:6A 00 push word 0 <<<<<<<<<########
ThePoint ³. 66:FF35 00204000 push word ptr [402000] ; Ú<%d> = 2012.
00401017 ³. 68 10204000 push offset 00402010 ; ³format = "%d
0040101C ³. FF15 C0204000 call near [<&msvcrt.printf>] ; ÀMSVCRT.printf
It is a"known" bug. BYTE-parameters also won't work correct.
It could be solved in the macro. For good reasons, Str$() is not affected :biggrin:
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
.data?
SysTime SYSTEMTIME <>
Init
invoke GetSystemTime, addr SysTime
Inkey Str$("SysYear=%i", SysTime.wYear)
Exit
end start
Quote from: qWord on June 10, 2012, 03:21:28 AM
the problem is probably, that wYear is a WORD, which cause the invoke macro to produce bad code -> move the value to a 32Bit GPR and then pass it to the macro:
movzx edx,SysTime.wYear
printf(...,edx)
You resolved my problem:
include masm32rt.inc
.data?
SysTime SYSTEMTIME <>
.data
.code
start:
invoke GetSystemTime, addr SysTime
movzx edx, SysTime.wYear
printf("%d\n", edx);
inkey "Press a key to continue ..."
invoke ExitProcess, NULL
end start
thank you all for the prompt response and solution. :biggrin:
If you like the printf macro, here is a solution:
printf MACRO format:REQ, args:VARARG
IFNDEF __UNICODE__
IFNB <args>
if type args eq WORD
movzx eax, args
fn crt_printf, cfm$(format), eax
elseif type args eq SWORD
movsx eax, args
fn crt_printf, cfm$(format), eax
else
fn crt_printf, cfm$(format), args
endif
ELSE
fn crt_printf, cfm$(format)
ENDIF
EXITM <>
ELSE
IFNB <args>
fn crt_wprintf, cfm$(format), args
ELSE
fn crt_wprintf, cfm$(format)
ENDIF
EXITM <>
ENDIF
ENDM
(I haven't touched the lower Unicode part)
Why not also test for a BYTE arg?
Quote from: MichaelW on June 10, 2012, 10:50:14 AM
Why not also test for a BYTE arg?
Maybe because MasmBasic cares already for lazy coders? :lol:
include \masm32\include\masm32rt.inc
printf MACRO format:REQ, args:VARARG
IFNDEF __UNICODE__
IFNB <args>
if type args eq WORD or type args eq BYTE
movzx eax, args
fn crt_printf, cfm$(format), eax
elseif type args eq SWORD or type args eq SBYTE
movsx eax, args
fn crt_printf, cfm$(format), eax
else
fn crt_printf, cfm$(format), args
endif
ELSE
fn crt_printf, cfm$(format)
ENDIF
EXITM <>
ELSE
IFNB <args>
fn crt_wprintf, cfm$(format), args
ELSE
fn crt_wprintf, cfm$(format)
ENDIF
EXITM <>
ENDIF
ENDM
.data
TheWord dw 12345
TheByte byte 222
TheSByte sbyte 222
.code
start:
printf("%i\tTheWord\n", TheWord)
printf("%i\tTheByte\n", TheByte)
printf("%i\tTheSByte\n", TheSByte)
inkey "bye"
exit
end start
I was sure that it was MasmBasic by jochen :biggrin:
http://foro.elhacker.net/asm/supuesto_buffer_overflow_con_printf_en_masm32-t363909.0.html
Quote from: RHL on June 10, 2012, 05:14:49 PM
I was sure that it was MasmBasic by jochen :biggrin:
Not really - I just modified the printf macro from the standard Masm32 lib.
In contrast to C printf, MasmBasic separates printing from the string format, which gives more flexibility, i.e. you can choose whether to print directly with Print Str$(), or assign an intermediate string with Let:
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
Init
mov ah, 111
Let esi=Str$("This is a byte: %i\n", ah)
Print esi
mov cl, 222
Print Str$("This is a byte: %i", cl), " - ", Hex$(cl), " as hex value", CrLf$
fldpi
Print Str$("... and this is PI:\n%Hf\n", ST(0))
Print "3.1415926535897932384626 is the expected value", CrLf$
Inkey "bye"
Exit
end start
It also can handle more input formats, e.g. xmm regs, FPU regs, REAL4... REAL10 etc.
You can even mix the input formats:
mov eax, 1000
movd xmm0, eax
fldpi
Print Str$("xmm0*ST(0)=%f\n\n", xmm0*ST(0))Output:
This is a byte: 111
This is a byte: 222 - DE as hex value
... and this is PI:
3.1415926535897932
3.1415926535897932384626 is the expected value
xmm0*ST(0)=3141.593Under the hood it's the same "if type eq REALX" technique used above for the modified printf.