1. Questions about makefile.wat
- Posted by bernie Apr 28, 2009
- 920 views
Are all the notes in the heading of makefile.wat file
correct, tested and work as described ?
Should any of the commands in WINALL have MANAGED_MEM=1
after the ( wmake -h -f makefile.wat ) commands ?
I see them after the DOSALL section but not in the windows section
Does anyone really know how all these files parameters are tied
together and interact ?
Why isn't there a single main makefile that just calls
a makefile for each compiler without having to pass back
and forth all these parameters ?
I still do not understand why turning on debug or using
SVN1705 or replacing be_call.c with that file from eu ver 3.11
makes my code work ?
That protecting the registers was a false hope.
I still think that something is wrong with managed memory
because this problem never occurred until after the source
was changed to default to managed memory.
Something was overlook in the changes or accidentally changed.
2. Re: Questions about makefile.wat
- Posted by DerekParnell (admin) Apr 28, 2009
- 906 views
I still do not understand why turning on debug or using SVN1705 or replacing be_call.c with that file from eu ver 3.11 makes my code work ?
Because it adds extra stuff that the compiler uses when it decides how to optimise things. Now, the compiler has decided that using the ESI register to strore a value is a good thing, and it assumes that you are not going to stuff around with that register.
That protecting the registers was a false hope.
No - it is not false hope. It is the correct and expected thing that your code should have been doing all along.
I still think that something is wrong with managed memory because this problem never occurred until after the source was changed to default to managed memory. Something was overlook in the changes or accidentally changed.
Again, no. Just fix your code, Bernie.
The internal workings of the compiler are out of our control. The best and proper way to do what you are trying to do is to code the assembler routine using the method as described in the compiler's documentation. Namely, save and restore all the registers you are going to use, except for EAX - EDX.
3. Re: Questions about makefile.wat
- Posted by jimcbrown (admin) Apr 28, 2009
- 880 views
Are all the notes in the heading of makefile.wat file
correct, tested and work as described ?
I haven't personally tested them. If you know of any that do not work as described, please post a bug report.
Should any of the commands in WINALL have MANAGED_MEM=1
after the ( wmake -h -f makefile.wat ) commands ?
No.
I see them after the DOSALL section but not in the windows section
MANAGED_MEM is unconditionally forced in the makefile. Not sure if this is really necessary, but DOS does not work without the old managed memory system.
Does anyone really know how all these files parameters are tied
together and interact ?
What are you asking?
Why isn't there a single main makefile that just calls
a makefile for each compiler without having to pass back
and forth all these parameters ?
The idea is to use the native makefile system for each compiler. That's why there are two makefiles. If you are asking why the makefile calls itself and sets parameters between invocations, well it is done because it is necessary.
I still do not understand why turning on debug or using
SVN1705 or replacing be_call.c with that file from eu ver 3.11
makes my code work ?
None of the makefile changes have anything to do with your code not working, unless we changed some compiler optimization settings, though.
That protecting the registers was a false hope.
Please explain. How did you protect the registers? Was it just ESI or did you protect all of them? What was the machine code that did this?
Protecting the registers should have worked. If it didn't then there is probably another bug in your machine code.
I still think that something is wrong with managed memory
because this problem never occurred until after the source
was changed to default to managed memory.
Something was overlook in the changes or accidentally changed.
Since Eu 2.x and Eu 3.x defaulted to managed memory, this can not be the case.
4. Re: Questions about makefile.wat
- Posted by jimcbrown (admin) Apr 28, 2009
- 898 views
I still do not understand why turning on debug or using
SVN1705 or replacing be_call.c with that file from eu ver 3.11
makes my code work ?
The fact that replacing be_call.c makes it work should have keyed you immediately to the fact that it was not a makefile change which caused it to break.
5. Re: Questions about makefile.wat
- Posted by bernie Apr 28, 2009
- 906 views
- Last edited Apr 29, 2009
-- Jim here is a simple example to add two numbers. -- It only uses stack pointer and eax register. -- Notice that I have pushed the registers that I -- think that eu could be using. -- -- Try running the program on WIN98 and note the reurn value -- Then comment out any push/pop of any register or all the of registers -- and see what the result returns. -- include std/machine.e include std/dll.e -- constant add_numbers = allocate(19) poke(add_numbers, { #56, -- 0: push esi ; #57, -- 1: push edi ; #52, -- 2: push edx ; #55, -- 3: push ebp ; #8B,#44,#24,#04, -- 4: mov eax, [esp+4] ; #03,#44,#24,#08, -- 8: add eax, [esp+8] ; #5D, -- C: pop ebp ; #5A, -- D: pop edx ; #5F, -- E: pop edi ; #5E, -- F: pop esi ; #C2,#08,#00}) -- 10: ret 8 ; -- you can change above to straight --> #C3}) -- ret integer rid1 = define_c_func("", add_numbers , {33554436,33554436}, 33554436) ? c_func(rid1,{15,17}) -- integer rid2 = define_c_func("", { '+',add_numbers }, {33554436,33554436}, 33554436) -- ? c_func(rid2,{15,17}) -- if getc(0) then end if -- pause
6. Re: Questions about makefile.wat
- Posted by jimcbrown (admin) Apr 28, 2009
- 895 views
- Last edited Apr 29, 2009
In no case do I get the correct result of 32.
I also tested on Linux.
-- Jim here is a simple example to add two numbers. -- It only uses stack pointer and eax register. -- Notice that I have pushed the registers that I -- think that eu could be using. -- -- Try running the program on WIN98 and note the reurn value -- Then comment out any push/pop of any register or all the of registers -- and see what the result returns. -- include std/machine.e include std/dll.e -- constant add_numbers = allocate(19) poke(add_numbers, { #56, -- 0: push esi ; #57, -- 1: push edi ; #52, -- 2: push edx ; #55, -- 3: push ebp ; #8B,#44,#24,#04, -- 4: mov eax, [esp+4] ; #03,#44,#24,#08, -- 8: add eax, [esp+8] ; #5D, -- C: pop ebp ; #5A, -- D: pop edx ; #5F, -- E: pop edi ; #5E, -- F: pop esi ; #C2,#08,#00}) -- 10: ret 8 ; -- you can change above to straight --> #C3}) -- ret integer rid1 = define_c_func("", add_numbers , {33554436,33554436}, 33554436) ? c_func(rid1,{15,17}) -- integer rid2 = define_c_func("", { '+',add_numbers }, {33554436,33554436}, 33554436) -- ? c_func(rid2,{15,17}) -- if getc(0) then end if -- pause
7. Re: Questions about makefile.wat
- Posted by jimcbrown (admin) Apr 28, 2009
- 877 views
- Last edited Apr 29, 2009
I can explain what the problem is.
You push 4 registers on the stack, but then do not account for that in your mov or add statements. So you end up adding the values of edx and ebp (which will probably be random junk) and returning that.
In no case do I get the correct result of 32.
I also tested on Linux.
-- Jim here is a simple example to add two numbers. -- It only uses stack pointer and eax register. -- Notice that I have pushed the registers that I -- think that eu could be using. -- -- Try running the program on WIN98 and note the reurn value -- Then comment out any push/pop of any register or all the of registers -- and see what the result returns. -- include std/machine.e include std/dll.e -- constant add_numbers = allocate(19) poke(add_numbers, { #56, -- 0: push esi ; #57, -- 1: push edi ; #52, -- 2: push edx ; #55, -- 3: push ebp ; #8B,#44,#24,#04, -- 4: mov eax, [esp+4] ; #03,#44,#24,#08, -- 8: add eax, [esp+8] ; #5D, -- C: pop ebp ; #5A, -- D: pop edx ; #5F, -- E: pop edi ; #5E, -- F: pop esi ; #C2,#08,#00}) -- 10: ret 8 ; -- you can change above to straight --> #C3}) -- ret integer rid1 = define_c_func("", add_numbers , {33554436,33554436}, 33554436) ? c_func(rid1,{15,17}) -- integer rid2 = define_c_func("", { '+',add_numbers }, {33554436,33554436}, 33554436) -- ? c_func(rid2,{15,17}) -- if getc(0) then end if -- pause
8. Re: Questions about makefile.wat
- Posted by jimcbrown (admin) Apr 28, 2009
- 926 views
- Last edited Apr 29, 2009
Sorry to quote myself twice in a row. But I've fixed bernie's machine code so it will work now.
These two lines:
#8B,#44,#24,#04, -- 4: mov eax, [esp+4] ; #03,#44,#24,#08, -- 8: add eax, [esp+8] ;
Should be changed to this:
#8B,#44,#24,#14, -- 4: mov eax, [esp+4] ; #03,#44,#24,#18, -- 8: add eax, [esp+8] ;
Then it works correctly in all cases on both 98 and linux.
I can explain what the problem is.
You push 4 registers on the stack, but then do not account for that in your mov or add statements. So you end up adding the values of edx and ebp (which will probably be random junk) and returning that.
In no case do I get the correct result of 32.
I also tested on Linux.
-- Jim here is a simple example to add two numbers. -- It only uses stack pointer and eax register. -- Notice that I have pushed the registers that I -- think that eu could be using. -- -- Try running the program on WIN98 and note the reurn value -- Then comment out any push/pop of any register or all the of registers -- and see what the result returns. -- include std/machine.e include std/dll.e -- constant add_numbers = allocate(19) poke(add_numbers, { #56, -- 0: push esi ; #57, -- 1: push edi ; #52, -- 2: push edx ; #55, -- 3: push ebp ; #8B,#44,#24,#04, -- 4: mov eax, [esp+4] ; #03,#44,#24,#08, -- 8: add eax, [esp+8] ; #5D, -- C: pop ebp ; #5A, -- D: pop edx ; #5F, -- E: pop edi ; #5E, -- F: pop esi ; #C2,#08,#00}) -- 10: ret 8 ; -- you can change above to straight --> #C3}) -- ret integer rid1 = define_c_func("", add_numbers , {33554436,33554436}, 33554436) ? c_func(rid1,{15,17}) -- integer rid2 = define_c_func("", { '+',add_numbers }, {33554436,33554436}, 33554436) -- ? c_func(rid2,{15,17}) -- if getc(0) then end if -- pause
9. Re: Questions about makefile.wat
- Posted by DerekParnell (admin) Apr 28, 2009
- 888 views
- Last edited Apr 29, 2009
Bernie, how much experience have you had with writing machine/assembler code?
The code you supplied is wrong, and here is why ...
On entry to your program the ESP points to the stack frame that your function can use. It looks like this ...
ESP --> ... ESP+4 --> parm1 ESP+8 --> parm2
Next your program pushes four 32-registers on to the stack. So now it looks like this ...
ESP --> EBP ESP+4 --> EDX ESP+8 --> EDI ESP+12--> ESI ESP+16--> ... ESP+20--> parm1 ESP+24--> parm2
Next you add the two values addressed by ESP+4 and ESP+8, that is you add the EDX and EDI registers together.
Pushing values onto the stack changes the ESP contents.
The usual way to write called routines is this ...
push ebp ; always pushed first mov ebp,esp ; copy the stack pointer so you have a fixed point of reference. push esi push edi ... push as many as you want ... mov eax, ebp+8 add eax, ebp+12 ... now pop them in reverse order. pop edi pop esi pop ebp ; always popped last ret
10. Re: Questions about makefile.wat
- Posted by mattlewis (admin) Apr 28, 2009
- 887 views
- Last edited Apr 29, 2009
I still think that something is wrong with managed memory
because this problem never occurred until after the source
was changed to default to managed memory.
Something was overlook in the changes or accidentally changed.
There might be, but I've not seen any evidence of any problems. That code hasn't changed since 3.1 (as Jim already said). The whole point of that is to ensure 8-byte alignment on systems that don't guarantee it already, and to cache memory allocations as an optimization. If you can figure out a plausible scenario where this is affecting you, and where the other changes we already talked about don't fix your problem, then we'll take a look at the managed memory code.
As it is, we discovered exactly what was going wrong. I'll restate the problem once again. For some reason, OpenWatcom decided that it could optimize code in call_c() by storing return_type in the ESI register. It didn't do this before. But after call_c() was changed, this optimization was used by OpenWatcom.
Unfortunately, you have some machine code that changes ESI, and doesn't set it back to what it was before your code was called. This means that before your code was called, return_type had a value of C_UINT (or whatever it was). After the call to your code returned, the value was changed to some other value that was used in your code.
After the call, the value of return_type is inspected in call_c() to determine how to convert the result from your call into a euphoria object, so that your euphoria code could use it. Unfortunately, since return_type no longer looked like a valid C_* value, call_c() didn't know what to do, and returned 0 as a default.
It might be better to trigger a fatal error in this case, since something bad has obviously happened. But the bottom line is that a bug in your code was uncovered. And it was relatively easy to track down. Imagine if call_c() hadn't used ESI at all, and therefore never pushed and popped it from the stack, thereby corrupting some other unsuspecting part of the interpreter. That would have been very hard to track down.
The moral of the story is that Bugs Happen. Please fix them when you find them, and take yes for an answer.
Matt
11. Re: Questions about makefile.wat
- Posted by bernie Apr 28, 2009
- 891 views
- Last edited Apr 29, 2009
Bernie, how much experience have you had with writing machine/assembler code?
The code you supplied is wrong, and here is why ...
On entry to your program the ESP points to the stack frame that your function can use. It looks like this ...
ESP --> ... ESP+4 --> parm1 ESP+8 --> parm2
Next your program pushes four 32-registers on to the stack. So now it looks like this ...
ESP --> EBP ESP+4 --> EDX ESP+8 --> EDI ESP+12--> ESI ESP+16--> ... ESP+20--> parm1 ESP+24--> parm2
Next you add the two values addressed by ESP+4 and ESP+8, that is you add the EDX and EDI registers together.
Pushing values onto the stack changes the ESP contents.
The usual way to write called routines is this ...
push ebp ; always pushed first mov ebp,esp ; copy the stack pointer so you have a fixed point of reference. push esi push edi ... push as many as you want ... mov eax, ebp+8 add eax, ebp+12 ... now pop them in reverse order. pop edi pop esi pop ebp ; always popped last ret
Thanks Jim & Derek
Yes I had tried this too.
push ebp ; always pushed first mov ebp,esp ; c
That was failing too.
I guess it is a problem with [esp+4] which I thought was getting the contents of the stack.
I was depending on pete's asm.e for the code.
Thanks.
12. Re: Questions about makefile.wat
- Posted by DerekParnell (admin) Apr 28, 2009
- 904 views
- Last edited Apr 29, 2009
Yes I had tried this too.
push ebp ; always pushed first mov ebp,esp ; c
That was failing too.
I guess it is a problem with [esp+4] which I thought was getting the contents of the stack.
I was depending on pete's asm.e for the code.
[esp+4] is getting the contents from the stack, just not the parameter data you were expecting because the pushes moved the parameters (relative to SP). You had hardcoded the +4 using the stack pointer. This is not a good idea. That is why the ESP (Base Pointer) was created. It is meant to be used by functions as the BASE of the stack frame for their use.
If you had of used [ebp+8] you can then push as much data onto the stack as you want and still not have to recalculate where the parameters are.
So to repeat...
All machine code functions should start with ...
push ebp mov ebp, esp add ebp, L ; Where L is total size of local variable space
And should end with ...
sub ebp, L mov esp, ebp pop ebp ret (N)
And then when addressing any stack-based parameters, calculate them relative to EBP and never use ESP in your function at all. The +8 is needed to skip over the saved EBP and the return address.
mov eax, [ebp + L + 8] ; Get top parameter on stack
Note, with Watcom, some parameters may be passed in registers and not on the stack at all. Read the manual for details.