Look I am a newbie.
I have readed every tutorial until 7.
I have trouble with Tutorial 6: Keyboard Input.
I understand the tutorial completly, but for any tutorial I come by I make an example in this case I took this code:

***

.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib

.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
char WPARAM 20h ; the character the program receives from keyboard

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?

.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT

.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CHAR
push wParam
pop char
invoke InvalidateRect, hWnd,NULL,TRUE
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
invoke TextOut,hdc,0,0,ADDR char,1
invoke EndPaint,hWnd, ADDR ps
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start

***

If you take the code and assemble it you will see that only one character can be showen at the time.
I wanted to change this to show more then one character, though only on one line, so I tried to make a register count how many letters there where.
The technique of this is that where the old characters was the screen would not be updated, only where the new character where(It's saves alot of time to do it this way and it should be easy. But it is not easy. Anyway it woulden't allow to change old characters.).
So if there was 12 characters a register would contain a number like 96("12*8", 8 is length of each character). Then it would just paint a new character a new place(using the number from the register (96) ) until there where no more space.

Diden't work.

:(

Why?

Well: I am newbie!
and: I suck when it comes to registers!

Why is that?

Well:I suck to registers cause the register tutorials are so booooooooooring. Lucky and unfortunatly for me the tutorials by Iczelion (that I like very much, indeed) did not cover registers that much.

My questions:

So what do I do?
Is my own code at line "79" right(Diden't work that well) ?

***

.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
add edx, 8
invoke TextOut,hdc,edx,0,ADDR char,1
invoke EndPaint,hWnd, ADDR ps
.ELSE

***

That code is placed instead of:

***

.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
invoke TextOut,hdc,0,0,ADDR char,1
invoke EndPaint,hWnd, ADDR ps
.ELSE

***

I mean what's wrong?
Is it the register type?
Is there another way to do this?

Does Iczelion in any tutorial cover registers specially?

:confused:

Julian


Here is a fact:
###
Once again a newbie needs help.
Finally when the newbie has got helped several times he is ready to help.
Then the circle is complete.
###
Posted on 2003-08-26 12:58:15 by JulianS
My sugestion is use a space in the data section, some like numberOfChars dd 0 and use it instead of the register.


About the registers some are trashed and others no (be calls to the api, and sure by your own procedures, functions, or whatever you call them, the api functions have a standar of what save and what i can trash, for your procedures you choice too what to trash and what to save ), you can read this at tut 1 I think or 2 in case that you dont have the answer there.

Hope that help.

Nice day.
Posted on 2003-08-27 08:17:02 by rea
Could you please show me how you would do it?

and what's a "dd" type?
I have only heard of db and dw, noting more.
Could you please give me a list of variable types?

Thank you.


Julian

Here is a fact that is very likely to be wrong
###
If variables and registers are stored in memory, then this is wrong:

Variables + registers = Memory

But even though, this is right:

Memory = Variables + Registers

That's cause registers and variables does not make memory, but memory makes them.
###
Posted on 2003-08-27 08:40:44 by JulianS
dd = declare dword, dw = declare word, db = declare byte and so on

When you call a function, most likely your edx/ecx/eax will be corrupted (you cannot take your chances), so if you want to use unmodified registers use ebx/edi/esi. However if you are the callback function, remember to preserve ebx/esi/edi because sometimes windows's code uses them, and if you corrupt the values in it....

If variables and registers are stored in memory, then this is wrong:

Variables + registers = Memory

But even though, this is right:

Memory = Variables + Registers

That's cause registers and variables does not make memory, but memory makes them.

I don't think you are correct. Registers can be access as both a data type or as a pointer to an address. Variables (ie global variables) are part of memory and local variables are part of the stack (which is also memory). So Memory != variables + registers. It all depends on how is the opcode used. When square brackets are present, it means that the data type is memory (except for lea).
Posted on 2003-08-27 09:04:49 by roticv
Than you very much for helping out.



dd = declare dword, dw = declare word, db = declare byte and so on
I don't think you are correct. Registers can be access as both a data type or as a pointer to an address. Variables (ie global variables) are part of memory and local variables are part of the stack (which is also memory). So Memory != variables + registers. It all depends on how is the opcode used. When square brackets are present, it means that the data type is memory (except for lea).


You could actually say:

.If OpCode = RightOpCode then
Memory = Variables
.EndIF

Right?

:-)
Posted on 2003-08-27 09:08:46 by JulianS
I mean something else



.data?
temp dd ?
.code
...
mov eax, offset temp
mov ebx, [eax]

is the same as


mov ebx, temp

Of course masm isn't technically correct. Fasm is more "correct" on this issue of square bracket = memory. Bah! I think I am making you more confused. Sorry for any confusion caused.
Posted on 2003-08-27 09:12:40 by roticv
Okay. Roticv would you please take a look at my code, and see what's wrong?

***

.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib

.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
char WPARAM 20h ; the character the program receives from keyboard
numberOfChars dd 0

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?

.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT

.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CHAR
push wParam
pop char
invoke InvalidateRect, hWnd,NULL,TRUE
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
add numberOfChars , 8
invoke TextOut,hdc,numberOfChars ,0,ADDR char,1
invoke EndPaint,hWnd, ADDR ps
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start

***

I belive that the wrong thing is the: "invoke InvalidateRect, hWnd,NULL,TRUE" ?t deletes the old text so I would actually need the program to remember all the text.
How can I make a variable put more text (words) on it?`
I mean if the varibale contains "H" then it would get the character "I" and make it "HI".
How could this be possible?

Sorry for having almost no knowglede of string manipulation.

Julian

Here is a true fact
###
Somebody will see this.
If this is a lie nobody knows.
###
Posted on 2003-08-27 09:21:00 by JulianS
I think you need to make some modifications.



.data
char db 64 dup (0)
.code
...
.ELSEIF uMsg==WM_CHAR
mov edx, wparam
mov ecx, offset char
@@:
cmp byte ptr[ecx],0
lea ecx, [ecx+1]
jnz @B
mov [ecx], dl
invoke InvalidateRect, hWnd,NULL,TRUE
...

If I am not wrong. Actually I do not think that string manipulation is difficult once you get the hang of it. Oh yes also change "add numberOfChars , 8" to "add numberOfChars,1 ".
Posted on 2003-08-27 09:30:03 by roticv

I think you need to make some modifications.



.data
char db 64 dup (0)
.code
...
.ELSEIF uMsg==WM_CHAR
mov edx, wparam
mov ecx, offset char
@@:
cmp byte ptr[ecx],0
lea ecx, [ecx+1]
jnz @B
mov [ecx], dl
invoke InvalidateRect, hWnd,NULL,TRUE
...

If I am not wrong. Actually I do not think that string manipulation is difficult once you get the hang of it. Oh yes also change "add numberOfChars , 8" to "add numberOfChars,1 ".


If you have tried it you will get a error about "wparam".
I belive you never created a variable named that.
Why is that?
But anyway what would you use it for?

When I tried to remove the variable nothing appeared on the screen.
Should you not make a loop or something?

Your help is very good.
Thank you.
Posted on 2003-08-27 09:43:32 by JulianS
My mistake. It should be wParam instead. :grin:

Okay let me explain the basics of the loop. Your code is like keep adding a character to a buffer (in this case the variable name is char). The loop scans for the null-terminator (Using The Svin's fiction point logic). Since the low byte of wParam is the character you need to add, the mov , dl copies the character to the buffer. I did not copy a null to the string as I had defined the buffer to be full of zeros.
Posted on 2003-08-27 09:49:50 by roticv
Sorry to mention it but still does not work.
No errors but either no text.
I change some settings for: "invoke TextOut,hdc, numberOfChars ,1,ADDR char, 1" and then I discovered that you might make a jump function that simply jumps until it meets 0(Null).
Could you show me how this is done?
Here is the code again fully manipulated:

***

.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib

.data
char db 64 dup (0)
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
numberOfChars dd 0

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?

.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT

.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CHAR
mov edx, wParam
mov ecx, offset char
@@:
cmp byte ptr,0
lea ecx,
jnz @B
mov , dl
invoke InvalidateRect, hWnd,NULL,TRUE
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
add numberOfChars, 8
invoke TextOut,hdc, numberOfChars ,1,ADDR char, 1
invoke EndPaint,hWnd, ADDR ps

.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start

***

A very true fact indeed
###
Hope you answer will be the last one, cause I am running low on facts.
###
Posted on 2003-08-27 10:00:59 by JulianS
Ohh, and please try the code you want to give me, to see if it is right or wrong.
And do you know any string manipulation tutorial?
That could really be usefull.
Thanks alot for you efforts in helping me.
Posted on 2003-08-27 10:03:41 by JulianS
I forgot about one crucial part of the loop. I forgot to dec ecx. :grin:



.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib

.data
char db 64 dup (0)
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
numberOfChars dd 0

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?

.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,
CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT

.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CHAR
mov edx, wParam
mov ecx, offset char
@@:
cmp byte ptr[ecx],0
lea ecx, [ecx+1]
jnz @B
dec ecx
mov [ecx], dl
inc numberOfChars
invoke InvalidateRect, hWnd,NULL,TRUE
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
invoke TextOut,hdc, 0 ,1,ADDR char, numberOfChars
invoke EndPaint,hWnd, ADDR ps

.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start

I tested it. It works (did some fooling around with the debugger). I do know some string manipulation tutorials but of course all you need to know is that strings are access via pointers. That's all, unless you want to learn the *slow* string opcodes. The other important fact is that strings usually are null-terminated, meaning ends with 0.
Posted on 2003-08-27 10:20:34 by roticv
There are still error.
I managed to get ride of some but not all.
Try looking at the picture I have got from my screen while assembling
Posted on 2003-08-27 10:40:48 by JulianS
You can search the board for string tutorial, maybe you will find some that are the same and maybe say tha are from other autor, i dont know what is the original... ;). Also I think you have the masm32 package, if i am not wrong the is included some .hlp files, you can find them usefull, and this are very compact maybe dont procide much information I think is the suficient information to start with.



Also you need see that the 'limit' is 64 char to be hold :D, is only for you whatch that ;).

char db 64 dup (0)


Nice day.

<<<<<<<<<<<<<<<<<<<<<<---EdiT

I dont see nothing?????? in the atached file?????????
Posted on 2003-08-27 10:42:08 by rea
Thank you hgb for your reply but I am still waiting from roticv's reply cause his code contains some errors.

Anyhelp would be appreciated.

Thanks for all roticv.
Posted on 2003-08-27 10:49:40 by JulianS
Hey JulianS,

What error do you speak of? Care to explain to me? Your bitmap seemed to contain nothing, unless there is a need for me to change specs :)
Posted on 2003-08-27 10:52:25 by roticv
Here are the errors:

%%%

<33> Error A2111: conflicting parameter definition
<35> Error A2008: Syntax Error : dword
<36> Error A2012: PROC, MACRO, or macro repeat directive must preced LOCAL
<37> Error A2012: PROC, MACRO, or macro repeat directive must preced LOCAL
<38> Error A2012: PROC, MACRO, or macro repeat directive must preced LOCAL
<54> Error A2006: undefined symbol : wc
<54> Error A2114: INVOKE argument type mismatch : argument : 10
<55> Error A2137: too few arguments to INVOKE

%%%

and that is just some of them.

Maybe I will need to update my compiler.
I will make a try.

Julian
Posted on 2003-08-27 12:19:38 by JulianS
Sorry the code worked perfectly well. Though you gotta change some things, cause of this forum. Some lines where like:

***

INVOKE Something argument, argument, ar /
gument / argument

***

Or something.
Thats why the errors came.
Anyway thanks.
But can you also show me how to delete old characters?
And could you please explain the loop in deepth.

Fact
###
I am a noob. (I am sure many people would agree on that.)
###
Posted on 2003-08-27 13:59:26 by JulianS
*shake my head*

Change the code to
made some mistake with my coding.


...
.ELSEIF uMsg==WM_CHAR
mov edx, wParam
mov ecx, offset char
@@:
cmp byte ptr[ecx],0
lea ecx, [ecx+1]
jnz @B
dec ecx
.if edx == 08h
mov byte ptr[ecx-1],0
dec numberOfChars
.elseif
mov [ecx], dl
inc numberOfChars
.endif
...

08h = backspace, so if backspace is pressed, instead of the usual copying of the byte in edx, you copy over 0 to cut the string shorter by one charcter. Oh well, at least it works.
Posted on 2003-08-28 06:52:02 by roticv