News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

The memory could not be read

Started by w0lfshad3, August 21, 2006, 09:51:13 AM

Previous topic - Next topic

w0lfshad3

NOTE: 2nd page branches into an optimization discussion and bug fixes.

http://wolfshade.home.ro/project1.asm



or

http://wolfshade.home.ro/error.JPG

Tedd

loop uses the value of ecx for counting the number of loops - of course, you know this because you're setting it for 4 loops :wink
When you call another function (MoveWindow, in this case), you should assume it will mess up the value of ecx (esi, edi, ebx, and ebp are generally safe, assume all others messed up; esp is a special case, but it's considered safe) - meaning every time you call MoveWindow, the value for ecx is made 'random' and it's no longer your counter.
Simple solution - push the value before the call, pop it afterwards.


xor ecx, ecx
mov ecx, 4
push esi
xor esi, esi
label2::
mov i, esi
  .
  .
push ecx    ; <****************
invoke MoveWindow, [ChildIDsArray+esi], temp1, 0, temp2, temp3, TRUE
pop ecx     ; <****************
inc esi
loop label2
pop esi


P.S. Post long code 'snippets' as zipped attachments :wink
No snowflake in an avalanche feels responsible.

w0lfshad3

If you would've assembled it you would've got a "cannot read memory location err" as the title suggests.
I didn't care for the MoveWindow part because the trouble starts since the CreateWindow loop at array indexing part i think where i try to move the returns of CreateWindow(child handles) into an array. The error is quite serious me thinks.

This part contains the problem i can't solve:
mov ecx, 13; i = 12
push esi
xor esi, esi
label1::
mov edx, 13000
add edx, ecx
mov temp, edx
push ecx
push esi
invoke CreateWindowEx, NULL, ADDR ChildClassName, NULL,\
WS_CHILDWINDOW + WS_VISIBLE,\
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,\
hwnd, [temp], hInstance, NULL
pop esi
mov [ChildIDsArray+esi], eax
add esi, 4
pop ecx
loop label1
pop esi

Tedd

I did assemble and run the code, and got the error.
I fixed it and then showed you how to fix it.
Try again before you start whining ::)
No snowflake in an avalanche feels responsible.

w0lfshad3

#4
Thank you, this did the trick, my problem is i don't know how to debug, i tought the problem was still in the first loop:

Now i got another problemĀ  :'( :boohoo: i made this program in c aswell an now they both don't do what i intended them to do:
make each child window appear as a rectangle and when it gets a mouse click draw an "X" on it, it uses a flag made out of window extra bytes; the code is made after i learned the "checker3" program of Charles Petzold's Programming Windows.
The rectangles are supposed to appear at the top of the client area at x == 0/4, 1/4, 2/4, 3/4 times cxClient(client area pixels), y == 0 and have the width 1/4 and height 1/7 times cyClient.

Can you point me to whats going wrong please? Again when i made the C replica, my poor debugging skills pointed me to the array in wich the child handles sit(it was not getting filled for some reason).

Can you give me a quick explanation of the OllyDebugger for example, commands(except step into, step over, go to address?)
I can't jump to a specific address w/o having to use "go to address" functionality, and i have to use that a lot to look at the values the registers hold, also i don't understand what that assemble after an double click on code does.

mov temp2, 4
fld1 ; 1
fld temp2 ; 4, 1
fdivp ST(1), ST(0) ; 1/4
fld cxClient ; cxClient, 1/4
fmulp ST(1), ST(0) ; cxClient*1/4
fstp temp2 ; temp2 = ST(0), FPU stack balanced

mov temp3, 7
fld1 ; 1
fld temp3 ; 7, 1
fdivp ST(1), ST(0) ; 1/7
fld cxClient ; cxClient, 1/7
fmulp ST(1), ST(0) ; cxClient*1/7
fstp temp3 ; temp3 = ST(0), FPU stack balanced

mov ecx, 4
push esi
xor esi, esi
push edi
xor edi, edi
label2::
mov i, edi

mov temp1, 3
fld i ; i
fld temp1 ; 4, i
fdivp ST(1), ST(0) ; i/4
fld cxClient ; cxClient, i/4
fmulp ST(1), ST(0) ; cxClient*(i/4)
fstp temp1 ; temp1 = ST(0), FPU stack balanced

push ecx
push esi
push edi
invoke MoveWindow, [ChildIDsArray+esi], temp1, 0, temp2, temp3, TRUE
pop edi
inc edi
pop esi
add esi, 4
pop ecx
loop label2
pop edi
pop esi


this doesn't work like this:

case WM_SIZE :
          cxClient = LOWORD(lParam) ;
          cyClient = HIWORD(lParam) ;
          for (i = 0 ; i < 4 ; i++)

            MoveWindow (hwndChild[i],
                         cxClient * i/4, 0,
                           cxClient * 1/4,  cyClient *1/7, TRUE) ;

Tedd

1. Use "finit" before you start using the fpu (only needs doing once in your program)
2. "cxClient*(1/7)" is the same as "cxClient/7"
3. "fld" and "fst" move floating point numbers from and to memory. You're using integers, so you want "fild" and "fist" (with or without 'p')
4. "fdivp ST(1), ST(0)" -- if st(0)=1 and st(1)=4, then this is 4/1 (not 1/4) which results in 4 (not 0.25)
5. there are mul and div instructions for integers anyway, so you don't actually need to use the fpu
6. MoveWindow changes the position of the window -- which is why neither program does what you want
   for drawing rectangles you want Rectangle (inside a WM_PAINT message)
7. functions mess up the values of ecx and edx, but not esi, edi, or ebx, so there's no need to keep push-popping these ;)

Now, here's your fpu stuff fixed. (Note this won't magically make rectangles appear, because you're using MoveWindow, not Rectangle)
Look at it carefully, there are a lot of small changes :wink

        mov eax,lParam
        mov edx,eax
        and eax,0ffffh  ;width
        shr edx,16      ;height
        mov cxClient,eax
        mov cyClient,edx

        mov temp2, 4
        fld1                    ; 1
;st(0) = 1.0
        fild temp2              ; 4, 1
;st(0) = 4.0, st(1) = 1.0
        fdivp ST(1), ST(0)      ; 1/4
;st(0) = 0.25

        fild cxClient           ; cxClient, 1/4
;st(0) = cxClient, st(1) = 0.25
        fmulp ST(1), ST(0)      ; cxClient*(1/4)
;st(0) = (cxClient*0.25)
        fistp temp2             ; temp2 = ST(0), FPU stack balanced

        mov temp3, 7
        fld1                    ; 1
        fild temp3              ; 7, 1
        fdivp ST(1), ST(0)      ; 1/7
        fild cxClient           ; cxClient, 1/7
        fmulp ST(1), ST(0)      ; cxClient*(1/7)
        fistp temp3             ; temp3 = ST(0), FPU stack balanced

        xor ecx, ecx
        mov ecx, 4
        push esi
        xor esi, esi
    label2::
        mov i, esi

        mov temp1, 3
        fild i                  ; i
        fild temp1              ; 3, i
        fdivp ST(1), ST(0)      ; i/3
        fild cxClient           ; cxClient, i/3
        fmulp ST(1), ST(0)      ; cxClient*(i/3)
        fistp temp1             ; temp1 = ST(0), FPU stack balanced



You don't need to learn to debug, you need to learn how your program works. Debugging isn't much use unless you understand your program first.
No snowflake in an avalanche feels responsible.

w0lfshad3

#6
Thank you, i will look carefully, i was about to start debugging(without much success perhaps).
Judging from your last post and status on forum i'm sure it will be fixed after i implement it all:).

finit initializes FPU, meaning it lets the assembler know when to initialize it right?

P.S. The C code was working by getclientrect() passing to rectangle() and drawing rectangle as big as the child windows from the childwndproc() in wm_paint; sry i only included the code needed to compare to the asm snippet i didn't think you would go that deep :)

Here is the whole C code if it matters, its the replica of this asm code hopefully it will help some1 else http://wolfshade.home.ro/project.txt *

*for some reason seems there is a block from this site i presume preventing me to link a cpp source?(link hit goes:403 Forbidden, you must copy/paste the link)

Tedd

finit initialises the fpu - it's an actual instruction for the fpu to clean its registers and go to 'default settings'

You won't need GetClientRect, as you already got the width and height in WM_SIZE, from which you calculated cxClient and cyClient, so you can go straight to drawing the rectangles in WM_PAINT :U
No snowflake in an avalanche feels responsible.

P1

Quote from: w0lfshad3 on August 22, 2006, 01:21:49 AMmy problem is i don't know how to debug...
Please consider this challenge as being the most important skill you could learn.

Regards,  P1  :8)

w0lfshad3

#9
In OLLYDBG i found that i get lasterr: ERROR_INVALID_WINDOW_HANDLE (00000578) on MoveWindow;
That comes from the initialization of the ChildIDsArray i mentioned in the first post of this thread.

Debugging further it seems that [temp] inserts the right value as an argument to the formal parameter hMenu.
However after i pass with F7 after that parameter it disappears? what does that mean?

When exiting CreateWindowEx EAX is 0 ??? It was supposed to contain a handle.This seems to be the problem but can't fix.

http://wolfshade.home.ro/Project.Asm   (keep refreshing it s a crappy ftp)

Tedd

Very good - you found the problem :wink
When CreateWindow returns zero, that means it failed -- creation of the child window failed.
Now you have to figure out why :bdg


Hint: When each child window is created, its ChildWndProc gets called, any messages you don't handle are passed onto DefWindowProc (this is correct). BUT what is the result of DefWindowProc? And what is the result of ChildWndProc? -- Are these the same? Should they be?

BIG HINT: ret
No snowflake in an avalanche feels responsible.

w0lfshad3

I had ret after DefWindowProc in ChildWndProc, stillĀ  nothing :'( :boohoo: In my code i had it in the whole time.

updated: http://wolfshade.home.ro/Project.Asm

Tedd


.else
invoke DefWindowProc, hwnd, uMsg, wParam, lParam
;THIS looks like a nice spot
.endif
xor eax, eax
ret

ChildWndProc endp
end start


Are you sure?
No snowflake in an avalanche feels responsible.

w0lfshad3


w0lfshad3

 :dance: Hurray, it just stroke me, i'm using WNDCLASSEX but only RegisterClass, now some child windows started appearing after i registered them right. Thanks for the help. :U