> I do put my data to be "printed" (funny how we still use that BASIC verb that doesn't mean what it says)
Use "cout" instead, much clearer

Three options, side by side:
include \masm32\MasmBasic\MasmBasic.inc
.code
txHelloData db "Hello data", 0
Init
int 3
print offset txHelloData, 13, 10
print offset txHelloData, 13, 10
print "Hello World", 13, 10
print "Hello World", 13, 10
Print "Hello David", CrLf$
Print "Hello David", CrLf$
EndOfCodeUnder the hood:
Address Hex dump Command Comments
004010BC |. CC int3
004010BD |. 68 24104000 push txHelloData ; /Arg1 = ASCII "Hello data"
004010C2 |. E8 8D000000 call StdOut ; \SkelMbEmpty.StdOut
004010C7 |. 68 57804000 push offset ??00EA ; /Arg1 = ASCII "
"
004010CC |. E8 83000000 call StdOut ; \SkelMbEmpty.StdOut
004010D1 |. 68 24104000 push txHelloData ; /Arg1 = ASCII "Hello data"
004010D6 |. E8 79000000 call StdOut ; \SkelMbEmpty.StdOut
004010DB |. 68 5C804000 push offset ??00F1 ; /Arg1 = ASCII "
"
004010E0 |. E8 6F000000 call StdOut ; \SkelMbEmpty.StdOut
004010E5 |. 68 60804000 push offset ??00F2 ; /Arg1 = ASCII "Hello World"
004010EA |. E8 65000000 call StdOut ; \SkelMbEmpty.StdOut
004010EF |. 68 6C804000 push offset ??00F8 ; /Arg1 = ASCII "
"
004010F4 |. E8 5B000000 call StdOut ; \SkelMbEmpty.StdOut
004010F9 |. 68 70804000 push offset ??00F9 ; /Arg1 = ASCII "Hello World"
004010FE |. E8 51000000 call StdOut ; \SkelMbEmpty.StdOut
00401103 |. 68 7C804000 push offset ??00FF ; /Arg1 = ASCII "
"
00401108 |. E8 47000000 call StdOut ; \SkelMbEmpty.StdOut
0040110D |. 68 80804000 push offset ra_lbl2 ; ASCII "Hello David"
00401112 |. 6A 01 push 1 ; /Arg2 = 1
00401114 |. 6A 02 push 2 ; |Arg1 = 2
00401116 |. E8 DE130000 call MbPrint ; \SkelMbEmpty.MbPrint
0040111B |. 68 80804000 push offset ra_lbl2 ; ASCII "Hello David"
00401120 |. 6A 01 push 1 ; /Arg2 = 1
00401122 |. 6A 02 push 2 ; |Arg1 = 2
00401124 |. E8 D0130000 call MbPrint ; \SkelMbEmpty.MbPrintOption 1 (Masm32 SDK, old style):
- 20 bytes per call
- reuses txHelloData (15 bytes extra
once)
- you can't see the string, it's declared far away, so you will have to add a comment to understand your own code
Option 2 (Masm32 SDK, modern style):
- 20 bytes per call
- creates a new "Hello World" and a new CrLf for each call, i.e. 15 bytes extra
per call- you can see the string right in your call
Option 3 (MasmBasic):
- 14 bytes per call (Arg3 -> ra_lbl2, /Arg2 = 1 -> push CrLf, /Arg1 = 2 -> 2 args)
- reuses "Hello David" alias offset ra_lbl2
- you can see the string right in your call
For the real bare metal fans, there is option 4, a dozen lines for each "hello world" (\Masm32\m32lib\stdout.asm):
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(Oops, StrLen is a Masm32 library function, is that allowed in bare metal code?)
Note the attached executable will throw an exception because of the
int 3. In OllyDbg, go to Options/Options/Just-in-time/Set OllyDbg to make Olly take over when the crash happens.