The MASM Forum

General => The Campus => Topic started by: Lonewolff on April 23, 2018, 03:39:53 PM

Title: Parsing a string for NULL terminator
Post by: Lonewolff on April 23, 2018, 03:39:53 PM
Hi guys,

A basic question involving a simple loop.  :biggrin:

I am trying to loop through a null terminated string and have the count until '/0' stored in ecx.

I have a message box in the middle of the loop for debugging purposes only, but am having trouble with an infinite loop.


; loop until '\0'
mov ecx, 0
lp:
invoke MessageBox, 0, addr szBuffer, addr szTitle, 0

mov eax, offset szBuffer
add eax, ecx
cmp eax, 0

inc ecx
jne lp


I am pretty sure I am probably comparing the address itself to zero and not the value.

Any help would be greatly appreciated.  8)
Title: Re: Parsing a string for NULL terminator
Post by: hutch-- on April 23, 2018, 03:49:37 PM
This is a simple one. If you want the result in ecx, use ecx instead of eax.

  slen proc pstr:DWORD
    mov eax, pstr
    sub eax, 1
  lbl:
    add eax, 1
    cmp BYTE PTR [eax], 0
    jne lbl
    sub eax, pstr
    ret
  slen endp


For the MessageBox so you don't get problems, use pushad before it and popad after it. Only do this for test code, they are too slow for production code.

What is happening is the code in MessageBox is overwriting the registers you are using.
Title: Re: Parsing a string for NULL terminator
Post by: russellgreen on April 23, 2018, 03:52:36 PM
Quote from: Lonewolff on April 23, 2018, 03:39:53 PM
Hi guys,

A basic question involving a simple loop.  :biggrin:

I am trying to loop through a null terminated string and have the count until '/0' stored in ecx.

I have a message box in the middle of the loop for debugging purposes only, but am having trouble with an infinite loop.


; loop until '\0'
mov ecx, 0
lp:
invoke MessageBox, 0, addr szBuffer, addr szTitle, 0

mov eax, offset szBuffer
add eax, ecx
cmp eax, 0

inc ecx
jne lp


I am pretty sure I am probably comparing the address itself to zero and not the value.

Any help would be greatly appreciated.  8)

mov eax, offset szBuffef
xor ecx, ecx
loopy:
cmp byte ptr [eax+ecx], 0
je endloopy
inc ecx
; message box code
jmp loopy
endloopy:



sorry for the sloppiness, posting from phone



Title: Re: Parsing a string for NULL terminator
Post by: russellgreen on April 23, 2018, 03:54:42 PM
nevermind, listen to hutch.   :biggrin:

I forgot about eax etc getting overwritten   ::)

I'm used to writing buggy code  :icon_mrgreen:
Title: Re: Parsing a string for NULL terminator
Post by: Lonewolff on April 23, 2018, 04:07:00 PM
Thanks guys!

I think the key thing was the 'cmp byte ptr'. This was the main thing that I was struggling with.

I'll have to start taking notes in a word document for these little intricate details.  :t
Title: Re: Parsing a string for NULL terminator
Post by: jj2007 on April 23, 2018, 05:02:56 PM
Some more tricks:include \masm32\include\masm32rt.inc

.data
HelloW db "Hello World", 0

.code
start:
; loop until '\0'
xor ecx, ecx ; same as mov ecx, 0 but much shorter
lp:
pushad
invoke MessageBox, 0, addr HelloW[ecx], chr$("Title"), 0
popad
inc ecx
cmp byte ptr HelloW[ecx], 0
jne lp
MsgBox 0, "bye", "Hi", MB_OK  ; a handy Masm32 macro
  exit

end start
Title: Re: Parsing a string for NULL terminator
Post by: Mikl__ on April 23, 2018, 11:07:19 PM
; GUI #
include win64a.inc
.data
count db 0
MsgBoxText      db "Win64 Assembly is Great!",0
MsgCaption      db "Uncle Remus tales: #2 MessageBoxIndirect",0
.code
WinMain proc
local mb:MSGBOXPARAMS
mov mb.cbSize,sizeof MSGBOXPARAMS
mov mb.hwndOwner,0
mov mb.hInstance,400000h
        movr mb.lpszText,MsgBoxText
movr mb.lpszCaption,MsgCaption
mov mb.dwStyle,MB_OK or MB_USERICON  or MB_HELP

      mov mb.lpszIcon,1000
      mov mb.dwContextHelpId,0
  mov mb.lpfnMsgBoxCallback,0
  mov mb.dwLanguageId,0
mov count,lengthof MsgBoxText
@@: lea ecx,mb
invoke MessageBoxIndirect
sub count,1
jnz @b
invoke RtlExitUserProcess,NULL
WinMain endp
end
; GUI #
include win64a.inc
.data
MsgBoxText      db "Win64 Assembly is Great!",0
MsgCaption      db "Uncle Remus tales: #2 MessageBoxIndirect",0
count db 0
.code
WinMain proc
local mb:MSGBOXPARAMS
mov mb.cbSize,sizeof MSGBOXPARAMS
mov mb.hwndOwner,0
mov mb.hInstance,400000h
        movr mb.lpszText,MsgBoxText
movr mb.lpszCaption,MsgCaption
mov mb.dwStyle,MB_OK or MB_USERICON  or MB_HELP

      mov mb.lpszIcon,1000
      mov mb.dwContextHelpId,0
  mov mb.lpfnMsgBoxCallback,0
  mov mb.dwLanguageId,0
mov edi,offset MsgBoxText
or ecx,-1
mov al,0
repne scasb
not ecx
mov count,cl
@@: lea ecx,mb
invoke MessageBoxIndirect
sub count,1
jnz @b
invoke RtlExitUserProcess,NULL
WinMain endp
end
Title: Re: Parsing a string for NULL terminator
Post by: LordAdef on April 24, 2018, 02:47:54 AM
Wolff,

Are you using the messageBox for debugging purposes?

If yes, I'd suggest you make a custom macro. It's really useful in these cases.

This is mine, simple and yet efficient:


console MACRO tt:REQ, tt2:VARARG
   PUSHAD
   printf (&tt, &tt2)
   printf ("\n")
   POPAD
endm

This is a nice approach. If you filled your code with this debug macro and temporarily want to bypass it, simply go to the macro and comment its code. Fast and easy
Title: Re: Parsing a string for NULL terminator
Post by: Lonewolff on April 24, 2018, 07:55:01 AM
Hi Lord,

Thanks for the code snippet and yep, it's for debugging.

Today, I'll take a step back and work more on the basics. Like a lot of eager newbies, I started my journey in the middle (which isn't a bad thing, I don't think).

I have had a taste and I know I can achieve what I want to do. My initial challenge was 'can I set up DirectX11 and draw a quad?'. I did that and much much more.   8)

So back to basics I go now  :t
Title: Re: Parsing a string for NULL terminator
Post by: LordAdef on April 24, 2018, 09:44:09 AM
Quote from: Lonewolff on April 24, 2018, 07:55:01 AM
Hi Lord,

Thanks for the code snippet and yep, it's for debugging.

Today, I'll take a step back and work more on the basics. Like a lot of eager newbies, I started my journey in the middle (which isn't a bad thing, I don't think).

I have had a taste and I know I can achieve what I want to do. My initial challenge was 'can I set up DirectX11 and draw a quad?'. I did that and much much more.   8)

So back to basics I go now  :t

Sweet!
Well, it makes life a lot easier, and it's simple because of what I mentioned.

console "This is a printf   %d   %d", eax, ebx
Title: Re: Parsing a string for NULL terminator
Post by: Lonewolff on April 24, 2018, 09:45:12 AM
Thanks man!

Learning bucket loads each day. I'm like a big old sponge  :lol:
Title: Re: Parsing a string for NULL terminator
Post by: LordAdef on April 24, 2018, 11:24:28 AM
Quote from: Lonewolff on April 24, 2018, 09:45:12 AM
Thanks man!

Learning bucket loads each day. I'm like a big old sponge  :lol:

Me too!!!!
Title: Re: Parsing a string for NULL terminator
Post by: aw27 on April 24, 2018, 07:30:25 PM
A professional :shock:  debugging alternative that does not create noise in the console and does not pop alien windows. And it integrates with the masm32 sdk.
You will use dbgview.exe to see what happens.


include \masm32\include\masm32rt.inc

DEBUGGING equ 1 ; Comment when done with debugging

dbg MACRO format:REQ, args:VARARG
    LOCAL dbg_buffer

IFDEF DEBUGGING
    .data
dbg_buffer byte 80 dup (0)
    .code
    pushad
    IFNB <args>
        fn crt_sprintf, offset dbg_buffer, cfm$(format), args
        fn OutputDebugStringA, offset dbg_buffer
    ELSE
        fn OutputDebugStringA, cfm$(format)
    ENDIF
    popad
ENDIF
ENDM

.code

main proc
dbg "Testing OutputDebugString"
dbg "Some string: %s, some value: %d", "hello there", 12

invoke ExitProcess,0
main endp

end main
Title: Re: Parsing a string for NULL terminator
Post by: jj2007 on April 24, 2018, 10:51:15 PM
Quote from: aw27 on April 24, 2018, 07:30:25 PM
A professional :shock:  debugging alternative that does not create noise in the console and does not pop alien windows. And it integrates with the masm32 sdk.
You will use dbgview.exe to see what happens.

Didn't see any output until I added ; OPT_Debug 1 (RichMasm's special features ;))
Quote from: jj2007 on July 01, 2016, 09:22:42 AM
OPT_Debug       1                       ; enable the heap debugger (useful if you suspect heap corruption; console only)

I know what you are doing but it's not obvious. Perhaps you should elaborate a little bit for the n00bs here. I am also curious what you mean with "does not create noise in the console". The output goes to the console, right?
Title: Re: Parsing a string for NULL terminator
Post by: aw27 on April 25, 2018, 12:01:28 AM
@JJ,

You will see the debug strings either with DbgView.exe from Microsoft, or, if you are using a debugger, you will see the output in the debugger output window only. So, the first one that grabs it is the one that views it because they are event based.
You can also produce your own "dbgview.exe", but will not be as powerful as DbgView.exe because this one works from kernel mode and can capture also ring 0 debug strings and user mode debug strings from different sessions (including when you launch the application as Administrator or another user).

Quote
Didn't see any output until I added ; OPT_Debug 1 (RichMasm's special features ;))
After my explanation, may be you can infer, and eventually fix the RichMasm problem.

Quote
The output goes to the console, right?
No, it does not, it appears in DbgView window.


Title: Re: Parsing a string for NULL terminator
Post by: jj2007 on April 25, 2018, 12:44:04 AM
Quote from: aw27 on April 25, 2018, 12:01:28 AMAfter my explanation, may be you can infer, and eventually fix the RichMasm problem.

There is nothing to fix, it works perfectly with RichMasm. Btw also with plain Masm32 code.

QuoteThe output goes to the console, right?
QuoteNo, it does not, it appears in DbgView window.

Cluttering my desktop with one more window??? That's clumsy. My version needs only one console. Besides, while it is of course possible to use OutputDebugStringA for printing stuff, it is IMHO more convenient to just use Alex' console MACRO or, in case you have MB installed, the real thing (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1019). RichMasm's OPT_Debug 1, btw, does not print anything except if it's necessary: when heap corruption is detected.
Title: Re: Parsing a string for NULL terminator
Post by: aw27 on April 25, 2018, 12:56:00 AM
Quote
Cluttering my desktop with one more window??? That's clumsy
This is what professionals use, probably because you have not convinced them yet to use RichMasm's OPT_Debug 1.  :icon_rolleyes:
Title: Re: Parsing a string for NULL terminator
Post by: LordAdef on April 25, 2018, 04:26:38 AM
MasmBasic is a beautiful project. So is RichMasm, the IDE.
Jochen is a prowd father of its creation and I admire his passion towards his library.
Title: Re: Parsing a string for NULL terminator
Post by: hutch-- on April 25, 2018, 05:11:42 AM
I bought a small piece of software that joins 2 computers in a novel way where you run the 2 monitors side by side and only use 1 mouse and 1 keyboard between them, it has clean communication between the two computer with the clipboard and I though I had found another use for my old i7 with Win7 on it but I already had another use of the old box which was downloading very big files onto a tail end HDD on my main machine.

I got tired of the dual screens very quickly, disconnected the software and just have to suffer silently with a 32 inch screen which is big enough to run 2 windows side by side. As my eyesight gets older, the solution is to buy a bigger monitor as the price of 50 inch and bigger TVs is still dropping and 4k may start to be viable in the not too distant future.
Title: Re: Parsing a string for NULL terminator
Post by: aw27 on April 25, 2018, 05:14:37 AM
Quote from: LordAdef on April 25, 2018, 04:26:38 AM
MasmBasic is a beautiful project. So is RichMasm, the IDE.
Jochen is a prowd father of its creation and I admire his passion towards his library.

I know you are one of the 2 users of MasmBasic, excluding JJ himself. I am expecting you to start developing your games in Masm Basic any time soon.  :t
I also like JJ, this is the reason I like to tease him.
Title: Re: Parsing a string for NULL terminator
Post by: LordAdef on April 25, 2018, 05:28:05 AM
Quote from: aw27 on April 25, 2018, 05:14:37 AM
Quote from: LordAdef on April 25, 2018, 04:26:38 AM
MasmBasic is a beautiful project. So is RichMasm, the IDE.
Jochen is a prowd father of its creation and I admire his passion towards his library.

I know you are one of the 2 users of MasmBasic, excluding JJ himself. I am expecting you to start developing your games in Masm Basic any time soon.  :t
I also like JJ, this is the reason I like to tease him.


Nice call Jose!









Title: Re: Parsing a string for NULL terminator
Post by: jj2007 on April 25, 2018, 09:33:04 AM
Thanks, Alex & José - I am so glad to have two real fans now ;)
Title: Re: Parsing a string for NULL terminator
Post by: HSE on April 25, 2018, 11:57:39 PM
Quote from: aw27 on April 24, 2018, 07:30:25 PM
A professional :shock:  debugging alternative

Very interesting your macro! The same idea can be used to make a wrapper to string debug in Vkim's DbgWin and Biterider's DebugCenter.  :t
Title: Re: Parsing a string for NULL terminator
Post by: daydreamer on April 26, 2018, 03:51:46 AM
Quote from: hutch-- on April 25, 2018, 05:11:42 AM

I got tired of the dual screens very quickly, disconnected the software and just have to suffer silently with a 32 inch screen which is big enough to run 2 windows side by side. As my eyesight gets older, the solution is to buy a bigger monitor as the price of 50 inch and bigger TVs is still dropping and 4k may start to be viable in the not too distant future.
I have DVI-HDMI cable from old stationary to big HD tv, but it is incapable of scale lower resolution to fullscreen than the max resolution, bought some converter for laptop VGA but it didnt work, so I tested some android screen mirror documents and tutorials on TV,if its not enough with a big tv, you can use smartphone to zoom function
some newer laptops also support screen mirroring on TV
int3 opcode is a exception for asm programmers, its one opcode that never gets optimized to go faster,because its a waste, you cannot debug faster