Why "\n" in a printf format string generates 0xD 0xD 0xA, i.e 2 carriages returns and 1 line feed?
You will be able to see it if you redirect the output to a text file.
Can you give as a source where it happens, please?
Here is one, and it definitely "happens", see attached executables and output:include \masm32\include\masm32rt.inc
.code
start:
printf("Here\nis\none")
exit
end start
Note the culprit is neither UAsm nor a notorious "third party include (http://masm32.com/board/index.php?topic=6508.msg69760#msg69760)" - this works fine:
print cfm$("Here\nis\nnone, hehe\n")
Note that invoke crt_setbuf, rv(GetStdHandle, STD_OUTPUT_HANDLE), 0 doesn't work, because C/C++ coders have their own ideas about stdout 8)
For the fans of hilarious and completely useless debates, here (https://stackoverflow.com/questions/9238576/is-it-safe-to-disable-buffering-with-stdout-and-stderr) and here (https://stackoverflow.com/questions/7876660/how-to-turn-off-buffering-of-stdout-in-c) are threads that could make you feel good to be an assembler programmer :icon_mrgreen:
:biggrin:
> For the fans of hilarious and completely useless debates, here and here are threads that could make you feel good to be an assembler programmer
:P
Interestingly, neither MASM assembler nor UASM when assembling 32-bit translate "\n"
;include \masm32\include\masm32rt.inc
;ml -c -coff printcr.asm
;link /SUBSYSTEM:console printcr.obj
.386
.model flat, stdcall
option casemap :None
includelib \masm32\lib\msvcrt.lib
printf proto C :ptr, :vararg
.data
format0 db "Here\nis\none"
.code
start:
invoke printf, offset format0
ret
end start
Produces this output when redirected to a text file:
Here\nis\none
And in C:
int main()
{
printf("Here\nis\none");
return 0;
}
Produces this, which is what is expected, when redirected to a text file:
Here
is
one
It is true that the masm32rt.inc produces:
Here
is
one
but I was not saying that masm32rt.inc has no bugs.
And that UASM when assembling 64-bit like this:
option casemap :None
OPTION frame:auto
OPTION WIN64:2
option LITERALS:ON
includelib \masm32\lib64\kernel32.lib
ExitProcess proto :dword
includelib \masm32\lib64\msvcrt.lib
printf proto :ptr, :vararg
.code
start:
invoke printf, "Here\nis\none"
invoke ExitProcess,0
end start
Produces this, when redirected to a text file:
Here
is
one
What appears to happen is that C translates "\n" to 0xA in the format string, probably for compatibility with Linux, and inside the printf code it will add the carriage return.
UASM 64-bit translates "\n" to 0xD 0XA. Inside the code printf adds another carriage return and the result is what we see.
Whats wrong with you guys, this is how a printf is handles in MASM32 thanks to a macro by Michael Webster.
Now come on, stop pulling our leg, write a MACRO that does it for you. :P
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this console app with
"MAKEIT.BAT" on the PROJECT menu.
----------------------------------------------------- *
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
printf("How D awl\nThis is how its done in 32 bit MASM\nThis is because MASM is a MACRO assembler.\n");
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
Hi Hutch!
The macro produced by Michael Webster produces this when output is redirect to a file:
How D awl
This is how its done in 32 bit MASM
This is because MASM is a MACRO assembler.
If your text editor does not show that there are undesirable lines separating each line of text, you will be able to see that there are two consecutive carriage return before the line feed looking at the file with a hexeditor. :t
Offset(d) 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
00000000 48 6F 77 20 44 20 61 77 6C 0D 0D 0A 54 68 69 73 How D awl...This
00000016 20 69 73 20 68 6F 77 20 69 74 73 20 64 6F 6E 65 is how its done
00000032 20 69 6E 20 33 32 20 62 69 74 20 4D 41 53 4D 0D in 32 bit MASM.
00000048 0D 0A 54 68 69 73 20 69 73 20 62 65 63 61 75 73 ..This is becaus
00000064 65 20 4D 41 53 4D 20 69 73 20 61 20 4D 41 43 52 e MASM is a MACR
00000080 4F 20 61 73 73 65 6D 62 6C 65 72 2E 0D 0D 0A O assembler....
Yes, you are right, I confess I have not had a look at that macro for a very long time.
This code,
main proc
print cfm$("How D awl\nThis is how its done in 32 bit MASM\nThis is because MASM is a MACRO assembler.\n")
ret
main endp
Produces when redirected,
How D awl
This is how its done in 32 bit MASM
This is because MASM is a MACRO assembler.
Press any key to continue ...
In hex,
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 48 6F 77 20 44 20 61 77 6C 0D 0A 54 68 69 73 20 How D awl..This
00000010 69 73 20 68 6F 77 20 69 74 73 20 64 6F 6E 65 20 is how its done
00000020 69 6E 20 33 32 20 62 69 74 20 4D 41 53 4D 0D 0A in 32 bit MASM..
00000030 54 68 69 73 20 69 73 20 62 65 63 61 75 73 65 20 This is because
00000040 4D 41 53 4D 20 69 73 20 61 20 4D 41 43 52 4F 20 MASM is a MACRO
00000050 61 73 73 65 6D 62 6C 65 72 2E 0D 0A 50 72 65 73 assembler...Pres
00000060 73 20 61 6E 79 20 6B 65 79 20 74 6F 20 63 6F 6E s any key to con
00000070 74 69 6E 75 65 20 2E 2E 2E 0D 0A tinue .....
Yes, but the "print" macro does not call the MSVCRT function "printf".
What happens is that cfm$ is doing more than is asked for. "\n" is only a line feed escape sequence not a carriage return+line feed escape sequence. There is an escape sequence to represent carriage return and it is "\r".
This makes it work with the macro "print" but not with the msvcrt function "printf".
Note that the msvcrt printf is smart enough to deal with format strings containing either "\n" or "\r\n" - it will never double the carriage return. What the msvcrt can't deal with is with a preprocessing of the format string replacing "\n" with 0xD + 0xA.
As a conclusion it appears that the problem is actually in the cmf$.
In my opinion, to avoid conflicts cmf$ should not do more than is asked for and just translate "\n" with 0xA. Who wants to use the macro "print" should write:
print cfm$("How D awl\r\nThis is how its done in 32 bit MASM\r\nThis is because MASM is a MACRO assembler.\r\n") and not print cfm$("How D awl\nThis is how its done in 32 bit MASM\nThis is because MASM is a MACRO assembler.\n")
Quote from: aw27 on September 03, 2017, 01:56:42 PMprintf adds another carriage return
Yes indeed, that is part one of the problem: The CRT tries to "improve" the output by inserting a CR when it hits a LF, so CR LF becomes CR CR LF. An archaic "feature" from the early days of console printing, which unfortunately has been added to the C standard by the wisecracks of ISO. Solution: avoid the CRT.
There is a second problem with crt_printf which appears when you use it together with a standard print function (and it can be solved with the same solution :bgrin:):
include \masm32\include\masm32rt.inc
.code
start:
mov esi, chr$(10, "This", 10, "is", 10, "the", 10, "CRT", 10) ; foolproof?
invoke crt_printf, esi
push esi
.While 1
lodsb
.Break .if !al
movzx eax, al
print str$(eax), " "
.Endw
pop esi
invoke crt_printf, esi
exit
end start
Output:
This
is
the
CRT
10 84 104 105 115 10 105 115 10 116 104 101 10 67 82 84 10
This
is
the
CRT
Perfect, isn't it? Now open a DOS prompt, launch the attached exe, and you'll understand why Micros**t programmers nowadays produce garbled error messages from MASM.exe (http://masm32.com/board/index.php?topic=5678.msg60531#msg60531) - they forgot to read the 1000-page C/C++ manual thoroughly :greensml:
Quote from: jj2007 on September 03, 2017, 05:19:49 PM
An archaic "feature" from the early days of console printing, which unfortunately has been added to the C standard by the wisecracks of ISO. Solution: avoid the CRT.
Unfortunately, I can not spend the whole day laughing. :badgrin:
Another interesting fact about the cfm$ macro is that it invented "masm specific escapes" like \l for <, \r for >, \x for !, \a for ( and \b for ). The most amazing is not that its steals the "\r" (carriage return escape) :dazzled:, the most amazing is that the escapes are absolutely unnecessary both for msvcrt prinft and for the GetStdHandle\WriteFile used by the print macro. :icon_eek:
No problem with Poasm :
.386
.model flat,stdcall
option casemap:none
option cstrings:on
printf PROTO C :DWORD,:VARARG
ExitProcess PROTO :DWORD
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\msvcrt.lib
.data
str1 db 'This\nis\na\ntest',0
.code
start:
invoke printf,ADDR str1
invoke ExitProcess,0
END start
CstringOption.exe
This
is
a
test
CstringOption.exe > Sample.txt
type Sample.txt
This
is
a
test
Disassembling the object module :
_data SEGMENT DWORD PUBLIC 'DATA'
str1 label byte
db 54H, 68H, 69H, 73H, 0AH, 69H, 73H, 0AH
db 61H, 0AH, 74H, 65H, 73H, 74H, 00H
_data ENDS
Quote from: aw27 on September 03, 2017, 06:20:34 PMthe most amazing is that the escapes are absolutely unnecessary both for msvcrt prinft and for the GetStdHandle\WriteFile used by the print macro. :icon_eek:
include \masm32\include\masm32rt.inc
.code
start:
; printf("Keep telling <nonsense>, José!") ; error A2045: missing angle bracket or brace in literal
; printf("Keep telling (nonsense\r, aw27!\n") ; error A2157: missing right parenthesis
; printf("Keep telling nonsense), aw27!\n") ; error A2046: missing single or double quotation mark in string
printf("Keep telling \lnonsense\r, aw27!\n") ; ! missing
printf("Keep telling \lnonsense\r, aw27\x\n") ; ! visible
exit
end start
Output:
Keep telling <nonsense>, aw27
Keep telling <nonsense>, aw27!
deleted
This too bad JJ, :( :( :(
And now I see the reason you say that MASM is getting worse at every edition. :badgrin: :badgrin:
Let's try it without using the macros. :greensml:
.386
.model flat, stdcall
option casemap :None
includelib \masm32\lib\kernel32.lib
GetStdHandle proto :dword
WriteFile proto :dword, :ptr, :dword, :ptr, :ptr
includelib \masm32\lib\msvcrt.lib
printf proto C :ptr, :vararg
strlen PROTO C :ptr
.data
format0 db "MASM 'specific characters' that need to be escaped (lol) <,>,!,(,)",13,10,0
.code
STD_OUTPUT_HANDLE equ -11
main proc
LOCAL bWritten : dword
LOCAL theLen : dword
LOCAL theHandle : dword
;1- Using GetStdHandle\WriteFile
Invoke strlen, offset format0
mov theLen, eax
Invoke GetStdHandle, STD_OUTPUT_HANDLE
mov theHandle, eax
Invoke WriteFile, theHandle,offset format0,theLen, addr bWritten,0
;2- Using msvcrt printf
invoke printf, offset format0
ret
main endp
end main
Output:
MASM 'specific characters' that need to be escaped (lol) <,>,!,(,)
MASM 'specific characters' that need to be escaped (lol) <,>,!,(,)
:bgrin: :bgrin:
:biggrin:
> Another interesting fact about the cfm$ macro is that it invented "masm specific escapes" like \l for <, \r for >, \x for !, \a for ( and \b for ). The most amazing is not that its steals the "\r" (carriage return escape), the most amazing is that the escapes are absolutely unnecessary both for msvcrt prinft and for the GetStdHandle\WriteFile used by the print macro.
The other amazing factor is it has been working perfectly for years and is not locked into the assumption level of high level languages but then it IS MASM. :P It writes to the screen correctly, can be redirected correctly and provides a few extra escapes that plug a hole in MASM's ancient macro notation.
Quote from: hutch-- on September 03, 2017, 10:33:38 PM
:biggrin:
The other amazing factor is it has been working perfectly for years and is not locked into the assumption level of high level languages but then it IS MASM. :P It writes to the screen correctly, can be redirected correctly and provides a few extra escapes that plug a hole in MASM's ancient macro notation.
I don't think so, see my example above. It redirects perfectly. :t
Quote from: nidud on September 03, 2017, 10:05:38 PM
http://masm32.com/board/index.php?topic=5250.0
Yep, I knew I had seen that before, thanks for reminding me :bgrin:
:biggrin:
> I don't think so, see my example above. It redirects perfectly
Yes but you have to use a high level language runtime to do it where MASM can use the API without that assumption and it is because MASM is a macro assembler. There are those of us who don't see assembler just as an accessory to some other high level language. :P
deleted
Quote from: hutch-- on September 03, 2017, 11:40:50 PM
Yes but you have to use a high level language runtime to do it where MASM can use the API
Actually MSVCRT.DLL is an operating system DLL, not a C runtime.
This is the situation since Windows 95 (https://blogs.msdn.microsoft.com/oldnewthing/20140411-00/?p=1273).
:biggrin:
That is a re-translation that does not work. Look at the name, the source and the format.
MS = Microsoft
VC = Visual C
RT = Runtime
It mirrors much of the C runtime library, it is not a Windows API DLL and it is almost exclusively in C format, not the API STDCALL.
Quote from: hutch-- on September 04, 2017, 12:54:11 AM
That is a re-translation that does not work. Look at the name, the source and the format.
MS = Microsoft
VC = Visual C
RT = Runtime
Were Microsoft in a position to give a new name of this historic msvcrt.dll without breaking thousands of applications it would have been done 20 years ago. As you know no company loves more changing names of things than Microsoft.
Quote
It mirrors much of the C runtime library, it is not a Windows API DLL and it is almost exclusively in C format, not the API STDCALL.
There is no specific C format, C functions can use any calling convention, as you know, and 99% of Windows is done in C. The Cdecl is similar to the stdcall, but is best for variadic functions, which abound in that msvcrt.dll. That was probably the reason for not compiling it for stdcall use. On the other end millions of DLLs exist that export stdcall functions and are not part of the Windows API. I don't think the calling convention should be the criteria for deciding if a DLL is part or not of the operating system. :biggrin:
deleted
Herein lies the difference, the reference material for the functions in MSVCRT is what it used for the normal C libraries whereas the Windows API functions are not, MSVCRT is what it says it is, a C runtime DLL that has been included in the OS versions since about Win95b. Everyone knows that STDCALL and C calling conventions are different so there is little point in trying to claim they are the same.
> Were Microsoft in a position to give a new name of this historic msvcrt.dll without breaking thousands of applications it would have been done 20 years ago
Have you seen the number of MSVC????.DLL versions there are ? They have long ago renamed their C runtime DLLs but left the old one alone.
> Or the re-translation of printf to ctr_printf, and then hog up these names with macros like exit() and printf().
That is because MASM is not VC and is not bould to give any credence to other languages naming conventions. Behind that statement is the assumption that assembler is a sub set of the C language where in fact it is not.
> Keep in mind that most of the .LIB files included with MASM32 loads msvcrt.dll and use these functions.
This is claptrap, the entire project uses some MSVCRT function calls which are mainly in macros but the vast majority of the MASM32 library is written in assembler and the source is there to prove it.
Quote from: hutch-- on September 04, 2017, 01:55:15 AM
This is claptrap, the entire project uses some MSVCRT function calls which are mainly in macros but the vast majority of the MASM32 library is written in assembler and the source is there to prove it.
The include file msvcrt.inc, which is part of the main include file masm32rt.inc of the SDK distribution, contains many hundreds of renamed functions with the crt_ prefix.
:biggrin:
Many of them are used all around the SDK.
:biggrin:
Quote
Behind that statement is the assumption that assembler is a sub set of the C language where in fact it is not.
It is not. Also C uses MASM without being a subset of MASM. :biggrin: :biggrin:
deleted
Not to mention that the user.dll exports Cdecl "API functions" like wsprintf, which are frequently used within the SDK.
I think we covered all aspects of the problem. :t
And a search within the \masm32\include directory tells that exist 80 *.inc files with PROTO C functions.
Quote from: aw27 on September 03, 2017, 10:38:07 PMsee my example above. It redirects perfectly. :t
No, your example doesn't redirect perfectly - you know that, of course.
But the whole point of macros like chr$() and cfm$() is that you can see what you want to write in context, not as WriteFile xyz, someobscurepointer. The line
print "Hello World" is much easier to read and understand. This is why "high level languages" were created. BASIC was the first major milestone there, but with the slow old machines, programmers were forced to use BASIC and assembly in parallel. Then, many years later, K&R decided to abandon BASIC and lift assembly to a higher level of abstraction, and to call it "C". The new "HLL" was almost as fast as assembly, but, as we still can see half a century later, it also maintained its closeness to the metal: pointers all over the place, the need to allocate and free explicitly even a simple hello world string, etc. The fact that M$ has to update the OS every month, and Adobe lost her reputation as a serious software company, is attributable to the habit of C/C++ to introduce bugs easily (I am trying to blame the language for the bugs, knowing how sensitive her programmers are :bgrin:)
In any case, please stop alluding that there is any parental relationship between C and assembly. Our baby was around long before K&R started their clumsy attempt to make assembly "easier".
@José: If you are looking for crt-free code, try MasmBasic ;)
Quote from: jj2007 on September 04, 2017, 03:02:26 AM
No, your example doesn't redirect perfectly - you know that, of course.
Of course, it redirects perfectly.
Quote
@José: If you are looking for crt-free code, try MasmBasic ;)
You invented a CRT MACRO that make a "just in time" assembly of the CRT functions. You are indeed a genius. :t
I apologize, but I think all aspects have been dealt with so, I will have to pass for further comments. :(
:biggrin:
> And a search within the \masm32\include directory tells that exist 80 *.inc files with PROTO C functions.
Have you counted the number of API prototypes that are STDCALL ?
> I was referring to the import libraries included with MASM32
Have you counted the number of API prototypes that are STDCALL ?
> The include file msvcrt.inc, which is part of the main include file masm32rt.inc of the SDK distribution, contains many hundreds of renamed functions with the crt_ prefix
Yes I know, I wrote the tool that created them. What you don't do is lose a massive number of names because they are used in another language, this allows the project to use any name it likes without being restricted by another language. In case anyone has missed it, MASM is a macro assembler that does not need a C compiler although it can easily use a module created in C if its done properly.
Quote
and is not bound to give any credence to other languages naming conventions.
> ..than C, PASCAL, STDCALL, FASTCALL, ...
I think you have missed the point here, MASM comes with NO RUNTIME LIBRARY at all, the vast majority of API functions are STDCALL, a few are in C, as far as I know there are no PASCAL functions and in 32 bit you can cook your own version of FASTCALL if you want to.
I know that you guys come from a different set of assumptions but I will make the point that MASM as a macro assembler can produce EXE, DLL, and OBJ files without any other help from C compilers.
LATER :
> These Windows API functions loads msvcrt.dll and use these functions, so MSVCRT is definitely a vital part of the package.
This is nonsense, you can call any of the entire Windows API function set without having to include MSVCRT.
Quote from: aw27 on September 04, 2017, 03:14:38 AM
Quote from: jj2007 on September 04, 2017, 03:02:26 AM
No, your example doesn't redirect perfectly - you know that, of course.
Of course, it redirects perfectly.
If you consider the CR CR LF at the end "perfect", then you are right, of course. But I vaguely remember that the OP started this thread because of such unwanted sequences 8)
QuoteQuote
@José: If you are looking for crt-free code, try MasmBasic ;)
You invented a CRT MACRO that make a "just in time" assembly of the CRT functions. You are indeed a genius. :t
Wow, that one I had completely forgotten! I wanted to be kind to C programmers in transition :bgrin:
But you can open any "normal" MasmBasic exe in PeView, you won't find the CRT loaded (unless Masm32 functions are used, of course).
Johnsa has fixed that \n\r stuff :t
New Uasm has been uploaded today :biggrin:
Please test it :greenclp:
aw27 source from the post #4
OPTION frame:auto
OPTION WIN64:2
option LITERALS:ON
includelib \masm32\lib64\kernel32.lib
ExitProcess proto :dword
includelib \masm32\lib64\msvcrt.lib
printf proto :ptr, :vararg
.code
start:
invoke printf, "Here\nis\none"
invoke ExitProcess,0
end start
here is the text:
0x0000000000A75000 48 65 72 65 0a 69 73 0a 6f 6e Here.is.on
0x0000000000A7500A 65 00 00 00 00 00 00 00 00 00 e.........
and here is output:
Here
is
one
Quote from: habran on September 05, 2017, 10:05:41 PM
Johnsa has fixed that \n\r stuff :t
New Uasm has been uploaded today :biggrin:
Please test it :greenclp:
@habran,
It fixes when assembling for 64-bit with LITERALS:On. :t
When assembling 32-bit with LITERALS:ON the escapes are not converted, though.
The escapes are also not converted, in either case, when not using LITERALS:ON and we just pass the address of the string. I think it is possible to do that as well without conflicting with the special characters used by the macros.
Good find :t
I'll pass it on Johnsa, it is his babe ;)
BTW, I am happy with your attitude and I appreciate your contribution for insurgence of UASM :eusa_clap:
Quote from: habran on September 05, 2017, 10:05:41 PM
Johnsa has fixed that \n\r stuff :t
Quote from: hutch-- on September 03, 2017, 10:33:38 PMit has been working perfectly
Was there something that needed fixing...? Don't underestimate the risk of breaking existing code. IMHO there was
nothing that needed a fix, except the CRT runtime that adds arbitrarily CR chars where it shouldn't - but that is clearly not our baby.
Hi,
I never put anything in to support the escapes in raw string data, as you can directly add the values yourself :
myString db "this is a string",13,10,0 for example
So at present they're only on the literals as directly used by invoke, I will look into the 32bit issue as they should function exactly the same! :)
Quote from: johnsa on September 05, 2017, 11:50:53 PM
I never put anything in to support the escapes in raw string data, as you can directly add the values yourself :
myString db "this is a string",13,10,0 for example
myString db "this",10,"is a",10,"string",10,0
is fine for the printf of msvcrt.dll. No
need to add the 13 in the end too.
The printf of Visual Studio is not the printf of msvcrt, it is a bit more intelligent.
@JJ,
No comments. :badgrin:
deleted
High-Level Console Modes (https://docs.microsoft.com/en-us/windows/console/high-level-console-modes)
QuoteENABLE_PROCESSED_OUTPUT: The backspace, tab, bell, carriage return, and line feed characters are processed
Problem is that I can't convince the OS to stop helping me: It always adds CR, even if the string contains only LFs ::)
Which makes the behaviour of CRT printf() even more suspect and superfluous. But I do remember that you could produce
These
stairs
have
five
stepswith a string containing only linefeeds. Or was that on Windows 98?
I still don't know why anyone bothers with "printf" when its such an archaic format from the days of DOS consoles and command line Unix. It is relatively easy to produce StdOut in both 32 and 64 bit Windows and simply by procedure design it both outputs to the screen and redirects with no problems at all. I just don't see the point of struggling to conform to ANSI 1989 or earlier when that world no longer exists. My only view is leave this historical junk to the out of date but backwards compatible C compilers.
At least when LITERALS:ON it would be useful to translate the remaining escape characters (backspace, tab, bell, carriage return). In particular because it is not possible to insert the codes in the middle, like I did above:
myString db "this",10,"is a",10,"string",10,0
And of course all this will be useful for any function, and there are many-the limit is the imagination- that would use a literal string, not only printf.
I am not here to participate in wars between C (or any other programming) and MASM. I don't think it makes sense and leads nowhere. Every programming language has its place. One think is undeniable, both C and MASM complement each other are are set to work together. Actually MASM can be used together with any HLL I am aware of, even the .Net languages. Still, makes a better match with C.
This is why I am a macro assembler man.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include64\masm64rt.inc
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
entry_point proc
LOCAL number :QWORD
mov number, 1234
conout chr$(9),"Leading Text", \
cfm$("\n\tHow D Awl\n\tthis is a converted number -\r "), \
str$(number),chr$(32,60,13,10,9),"Trailing Text",lf
waitkey
.exit
entry_point endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end
Which outputs to the screen,
Lead Text
How D Awl
this is a converted number -> 1234 <
Trailing Text
Press any key to continue...