The MASM Forum

Projects => Rarely Used Projects => GoAsm => Topic started by: shankle on June 26, 2012, 12:49:14 AM

Title: error msg?
Post by: shankle on June 26, 2012, 12:49:14 AM
Getting the following error message:
  "use square brackets to address memory, address , offset to get address"

     This is the offending code:  cmp D[iMsg], WM_CREATE

    Wndproc FRAME hWnd, iMsg, wParam,lParam
The Wndproc is before the cmp.

This same code appears in Donkeys Except and FontDlg.
Title: Re: error msg?
Post by: Ryan on June 26, 2012, 02:35:39 AM
What is D?

cmp iMsg, WM_CREATE
should work.
Title: Re: error msg?
Post by: shankle on June 26, 2012, 02:42:00 AM
"D" in GoAsm represents a DWORD
Title: Re: error msg?
Post by: satpro on June 26, 2012, 03:03:04 AM
Do you have WM_CREATE defined?  It's (I'm pretty sure) in winuser.h
GoAsm thinks WM_CREATE is a label in your program.

Do you have these in your main assembly file?:

#define LINKFILES
#include "windows.h"

(winuser.h will be loaded by windows.h)
Title: Re: error msg?
Post by: Ryan on June 26, 2012, 03:06:33 AM
Ah.  I didn't realize I was in GoAsm.

Carry on.
Title: Re: error msg?
Post by: satpro on June 26, 2012, 03:07:22 AM
shankle,
Look through those header files.  It really helps later.  For example, next time you get that message you'll know it was something you forgot to define.  If you aren't using them now--get Donkey's headers.
http://donkeysstable.com/ (http://donkeysstable.com/)
Title: Re: error msg?
Post by: shankle on June 26, 2012, 04:38:20 AM
Hi Satpro,
No I did not have them defined. Was trying to use "EQUs" to do the job.
I included them in the program and got other opportunities.
Have no idea where #define linkfiles is coming from.

Anyway here is what I added to my program.
  Const Section
  #include winuser.h
  #include windows.h
  #define linkfiles

These are the errors that windows.h caused:
  Line 299 of the include file Windows.h could not open file #include "windef.h"

  Line 303 of the include file windows.h - unexpected material <ntddi-win9xall>.

  WM_CREATE and others are in "winuser.h". Got the following error in winuser.h:
  "winuser.h - could not evaluate expression in conditional directive - winver".

Is it possible that these files don't work in Windows 7??????

  Nothing is ever easy.....
  Thank you for helping - I'm so green
Title: Re: error msg?
Post by: wjr on June 26, 2012, 11:20:26 AM
The files do work on Windows 7. Windows.h should be listed first, and as mentioned in Reply #3, winuser.h will be included so you do not need that line. Also, symbols are case sensitive, so use LINKFILES - this is a link switch which "If defined passes the name of the appropriate DLL to GoLink at compile time". Order is important too, so this needs to be defined before including windows.h.
Title: Re: error msg?
Post by: Yuri on June 26, 2012, 12:35:00 PM
Quote from: shankle on June 26, 2012, 04:38:20 AM
Anyway here is what I added to my program.
  Const Section
  #include winuser.h
  #include windows.h
  #define linkfiles
I think it's better to put these includes and defines before all sections.
Title: Re: error msg?
Post by: dedndave on June 26, 2012, 02:07:39 PM
you shouldn't need to open a CONST section for those
- nor for equates (i see that quite often   :P )
Title: Re: error msg?
Post by: shankle on June 28, 2012, 12:25:50 AM
I have disabled "windows.h". If I run with it I get errors in windows.h.
I have gone into the program and added an "A" to every API in the program.
When I link they all show up as unresolved.
More than that these items also show up as unresolved:
cbsize,  hwnd, msg, msh.param, hdc, FF_ROMAN, hdcPrn
??
Title: Re: error msg?
Post by: wjr on June 28, 2012, 10:37:21 AM
LINKFILES is used within the header files. Without "windows.h", since not every API function has an ANSI/Unicode variant, it sounds like you need to list the required DLL(s) that you import from (ex. Kernel32.dll, User32.dll, Gdi32.dll) to the command line for GoLink.

FF_ROMAN is defined in the header files (wingdi.h). As for the rest, those look more like they should have been defined within your source files.
Title: Re: error msg?
Post by: shankle on June 28, 2012, 11:09:38 AM
Hi Wjr,
Thanks for helping.
If I understand you correctly, that would make the GoAsm command line Huge. There are about
two dozen of them. I really don't think I understand.
I will check out the wingdi.h for FF_ROMAN.
Title: Re: error msg?
Post by: wjr on June 28, 2012, 11:58:19 AM
Correct - if you have that many and are not using the header files with LINKFILES, some alternatives to simplify things would be (see GoAsm+GoLink documentation for details) use of the following in your source:

#dynamiclinkfile path/filename

or a command file for use with GoLink:

GoLink @commands.txt
Title: Re: error msg?
Post by: shankle on June 28, 2012, 09:43:01 PM
Thank you WJR for your patience.
I just found the GOLINK manual. Thought every bit of documentation was in the
GoAsm manual. No wonder I was having problems.
Title: Re: error msg?
Post by: Ghandi on June 28, 2012, 10:23:46 PM
It all comes back to not having the necessary header files included, if a data type is used (ie: struct) then the header file which declares it is needed. Otherwise any reference to the type will flag an error, whether it be the type itself or declaring an instance of it/accessing an instant of it.

It's been the same for every language/tool i've coded with, i could be wrong but i don't think it would be any different for GoAsm would it?

HR,
Ghandi
Title: Re: error msg?
Post by: satpro on June 29, 2012, 01:28:02 AM
shankle,
Reading through your posts again it occurred to me that you might be having problems with the header files because of a directory issue.  When I first set up the files on my computer nothing would work right.  It turned out I was in the wrong directory to pull the headers.  Then I added something like this in a .bat file:

cls
set INCLUDE=P:\GoAsm\Includes
GoAsm /l /b /c "dd.asm"
GoLink "dd.obj"

The "set" line fixed the problem.  But disregard the "P:\GoAsm\Includes" part.  Use your include directory instead.  "cls" just clears the console so you know where you're at while compiling.
Title: Re: error msg?
Post by: shankle on June 29, 2012, 11:11:07 PM
Thanks guys for all your efforts to help me.

All of the header files from Mr. Hansen's site are on my puter as follows:
     GoAsm(g:) \include
I made a file to put the includes in:  MyProgbrs.h  #include \include\windows.h
This is what's in the Assembler program: #define LINKFILES,  #include MyProgbrs.h
The batch file is as follows: MyProgbtch.bat, set include, GoAsm(g)  /l/b/c \include\
  MyProgbrs.h MyProg.asm
Not trying to link as yet.

This is what I got when running  MyProgbtch.bat:
    Warnings....
line 299 of the include file \include\windows.h: - Could not open file:- #include
  "windef.h"
Line 303 of the include file \include\windows.h:- Must declare a section first -
Use DATA SECTION ["name"}, CODE SECTION ["name"] or CONST SECTION
["name'] or just DATA, CODE or CONST: .DATA, .CODE or .CONST 
Title: Re: error msg?
Post by: dedndave on June 30, 2012, 01:35:29 AM
hi Jack,
what you may need to do is to set an environment variable
My Computer - Properties (or Control Panel - System icon)
Advanced Tab
Environment Variables button
you can create variables that will apply to the current user, or system-wide (applies to all users)

according to Edgar's notes...
QuoteYou must create an INCLUDE environment variable with the path to these header files
See "Include files - using #include and INCBIN" in the GoAsm manual for details
so you want something like
INCLUDE=G:\GoAsm\include
Title: Re: error msg?
Post by: satpro on June 30, 2012, 01:39:23 AM
Can you do a copy/paste and show exactly what your set line looks like?  It's definitely the INCLUDE variable, and you can do it in the batch, which is slightly more convenient, or you can make an environment value, as stated above.  But it's definitely the INCLUDE...

Edit:  Also, once you set that variable up you won't need the "\include\" added to your #include statements.  You can just go:
#include "windows.h".  The INCLUDE variable does the subfolder work for you.
Title: Re: error msg?
Post by: shankle on June 30, 2012, 02:08:50 AM
Set INCLUDE
GoAsm /l/b/c \include\MyProgbrs.h MyProg.asm
;GOlINK /unused "MyProg.obj"

yep, Think it should be:
GoAsm /l/b/c \MyProgbrs.h MyProg.asm

If I understand you all correctly the Set command should be as follows:
Set INCLUDE=G:\GoAsm\include
Guessing!!!
Title: Re: error msg?
Post by: dedndave on June 30, 2012, 02:17:38 AM
correct...

if you do:
set INCLUDE
with no parameter, it simply displays the current value of that variable

if you do:
set INCLUDE=
with no parameter, it removes the variable from the environment table
Title: Re: error msg?
Post by: satpro on June 30, 2012, 03:00:42 AM
shankle,
Everybody does things a bit differently, but this is sort of how I do it, using your directory structure:

The batch file:
----------------
cls
set INCLUDE=G:\GoAsm\include
GoAsm /l /b /c "MyProg.asm"
GoLink "MyProg.obj"  (sometimes you'll put a dll here, after a space, e.g.  ddraw.dll)

In the assembly file My Prog.asm:
------------------------------------
(at the top of the file--first)
#define LINKFILES
#define DONKEYLIB_H

#include "windows.h"            ;Windows defs
#include "macros.h"             ;GoAsm macros (incl. CoInvoke)
#include "ddraw.h"               ;only if you use it
#include "MyProgbrs.h"        ;your header files...
#include "some_other_assemfile.asm"

DATA SECTION
today         dd  29
tomorrow  dd  ?
nextweek   dd  today+7-30

CONST SECTION
June = 6
July = 7 (or, = June+1)

CODE SECTION
Start:
mov eax, [today]
inc eax
mov [tomorrow], eax
....


This will assume your assembly files (and your own header files, if you wish) are in the GoAsm folder, along with GoLink.exe.  The GoAsm manual describes the order in which the assembler looks for your included files, but if you put them in the GoAsm folder--you'll always be okay, although maybe a bit cluttered.  When I have stuff in weird places I'll hard-code the location:  #include "X:\movies\great movies\star trek.wav" (you wouldn't incl a wav file)
Usually, just copy that wav file to your working (let's say GoAsm) folder.  You might mess it up or delete it by accident.  Why lose the original?

In "some_other_assemfile.asm" you can put DATA, CODE, and CONST SECTIONS (and should) just like in the main file.  Keep your assembly files short and focused for organization, named for what they do. I usually limit them to one main routine (plus obvious support stuff) and that's it.   GoAsm is blisteringly fast, so don't worry AT ALL about lots of files and long compile times.  It won't happen.  If you use a tabbed multi-view editor like Notepad++ you can automate the whole thing, just like an IDE.

I just wrote this up quick.  If someone spots something wrong, please point it out.
Bert
Title: Re: error msg?
Post by: shankle on June 30, 2012, 05:17:54 AM
Some success. The compile worked.
The link failed........

Here are my latest changes:
  MyProg.asm:  #define LINKFILES,  #define include.h (what I named Mr. Hansen's
   header files),  #include windows.h
  MyProgbtch.bat:  Set INCLUDE=g:\include.h,  GoAsm /l/b/c MyProg.asm, GoLink
   /unused "MyProg.obj"

Error message from GoLink: g:\>GoLink /unused "MyProg.obj" 'GoLink' is not
  recognized as an internal or external command operable program or batch file
GoLink is in the GoAsm(g) folder. MyProg is now a folder in the GoAsm folder.
Thanks guys
Title: Re: error msg?
Post by: dedndave on June 30, 2012, 05:33:49 AM
in the batch file, specify the full path of GoAsm.exe and GoLink.exe

otherwise, you can add that folder to your PATH environment variable (similar to directions above)
the individual elements of the PATH variable are seperated by semicolons

you can add a folder to the PATH variable temporarily in the batch file with:
SET PATH=G:\GoAsm;%PATH%
that adds the G:\GoAsm folder to the already existing list of other folders that you have

when you modify an environment variable in a batch file, it is only valid for the life of the console window
Title: Re: error msg?
Post by: MichaelW on June 30, 2012, 02:37:38 PM
Also, depending on what tools you have on your path and how many tool names are duplicated, you may have to control the order of the directories so that the correct tool will be found first.
Title: Re: error msg?
Post by: satpro on June 30, 2012, 09:16:31 PM
MichaelW,
I've read your posts before and have learned from you.  Thank you.  One of the names I trust.  Please explain what you mean to shankle in ordinary terms.  I have no idea what you are saying, and only sort of at that, so this guy is brand new and really wants to learn this stuff.  Why not be clear?  Let's make this a big tent.  It wasn't too long ago I came here looking for the next step after 65816ville and you guys helped me over and over again.  Now I "get" it.  Learning GoAsm is not easy.  Masm is the popular and a "just perfectly fine" assembler, but we are here because GoAsm is literally the best assembler anyone has ever written.  Let's help shankle--and every other person with the guts to program in assembler.  And maybe, just maybe--someday let's all collaborate on a project together...

shankle,
Before I start this "whatever you call it" I want to strongly emphasize you read the GoAsm manual again.  And again.  Really.  Jeremy wrote this effing excellent assembler, and he explains it well in the manual, but his coding examples will probably seem very foreign to you.  He uses a lot of absolute references to places in memory, using numbers (e.g. +8) instead of labels, especially in the stack.  He references memory in a very simple fashion--sort of old school.  If you understand 6502, the x86 stack is about the same--but much larger in terms of its use.  256 bytes ($0100-$01FF) for a stack is nothin' today.

What Dave is saying is to create an Environment variable.  His advice is good.  If you do that you won't have to do the repetitive task of including the "set" line in your .bat file.    It's true that the "set" line is only good for the life of the console.  Well, that's the life of your programming session-normally.  Now, you can do that, and you'll be fine, but what if, and I am testament to this, you change your entire scheme between "now" and "then"?  Your programming playground may change.  You may want a clean, new place to work.    You might begin new work on drive "X."  An environment variable is in the system.  It's automated.  It doesn't change.  But---you change.
So what do you do?
This is the reason why I like the idea of a .bat file.  When you type "myprog.bat" in the command line you transfer control to a file you wrote that assembles and links your program.  It simplifies the mystical process of compiling your program into an .exe.  I gave you a working outline in an earlier post.  It's all about the current (working) directory, and GoAsm follows that premise.  Your .bat file is in the GoAsm folder, as is GoAsm itself (and your files), so the compile process works from there.

Now, why would you name a folder "include.h"?  That's a name for a file.  You are a programmer, right?  Give your folders a proper name--minus an extension.  GoAsm looks first in the current folder, and then scours the drive(s) based on a logical formula (defined in the manual) for your files.  Remember my batch file example?  Try this layout:

G:
\GoAsm
GoAsm
GoLink
your assembly files
your personal .h files
your data files
the star trek .wav file

GoAsm\Help
...all your help files, including .pdf. chm, hlp, txt, doc (and anything else that might help you while programming)

GoAsm\include
Donkey's (Mr. Hansen's) files
other stuff you accumulate, such as number conversions, etc.

Relax.  Seriously.  I went through this--it was a tough nut to crack--and I've been breathing ASM since like 1975.  I don't know--before 8-bit floating point.  You'll get this and you'll be better for it.  Get your directories in order--right now.  They're fugged up (seems to me).  Go simpler.

All assy programmers are brothers...
Title: Re: error msg?
Post by: shankle on June 30, 2012, 11:41:04 PM
Hi Satpro,
Thanks for staying with me. I'm just about to give up on GoAsm.  A 15 second compile and link
has taken me several days and I am no closer than on the 1st day.
Include.H is Mr. Hansen's entire header file. Ok I can see the value of renaming it and
I will. Yes, I think I have had my directories/folders all messed up.
I like the idea of a bat file where all the goodies of one program are kept.

Of course I have become lazy using MASM32. Never have to go through all this.
I have read the manuals and understand quite a bit of it. But I need more examples
to get me started. Once over this hurdle I will test MyProg-32 bit and see if that works.
Then I have to covert it to 64-bit GoAsm. If I get that far.........
Title: Re: error msg?
Post by: dedndave on July 01, 2012, 12:59:46 AM
 :biggrin:

hang in there, Jack   :t

satpro...
what Michael is talking about does not seem to apply to Jack's current dilema
but - let's say you have 2 different programs named shuffle.exe
one is in folder A and the other is in folder B
both folders are in the PATH environment variable
the operating system will use the shuffle.exe program from the folder which appears first in the PATH
UNLESS - the current folder has a program named shuffle.exe, then it would be executed
but - it is possible, that you may have to re-organize the folders in the PATH variable so that the OS finds the one you want first

a similar problem may arise because of the extension type
DOS executed BAT files before COM, before EXE
so - if you had a shuffle.bat file and a shuffle.exe file in the same folder, the batch file would execute
later operating systems had an entry in win.ini to set the order
now, there is a PATHEXT environment variable that determines the order

however, in Jack's case, the OS is simply not finding the GoLink.exe file
this can be solved by locating the executable and adding the full path to the batch command
or it can be solved by making sure that folder is in the PATH variable
another option is to copy GoLink.exe to a folder that is in the PATH   :P
Title: Re: error msg?
Post by: shankle on July 01, 2012, 05:02:37 AM
State as of today 6-30-2012.
Not trying to link just compile the program.
MyProg.asm:  #define LINKFILES, #define jpsdhrs,  #include \windows.h

MyProgbtch.bat:  Set INCLUDE=g:\jpsdhrs,  Set PATH=g:\jpshdrs,  Set PATH=g:\goasm.exe,
  GoAsm /l/b/c  MyProg.asm

This is what's in the g:\GoAsm directory/folder:
  C99, GDIPlus, golink, Garejorg, gozips(all the saved GO Zips), JG, jpshdrs(Mr. Hansen's
  Header files), cmdline.txt, forhelp.txt, GoAsm.chm, goasm.exe, MyProgbtch.bat,
  MyProg.asm, cedt.cmd, cedt.exe, cedt.mac AND about 50 *.h files I moved to the
  g:\GoAsm directory/folder. Couldn't get a clean compile without doing it. There
  has to be  a better way.
Think I have the folder set up correctly. Not sure of the batch or program settings.

Here is the ERROR message I got when running MyProgbtch.bat:
Error!  The system could not make the OBJ/LST output file. OBJ file not made.
Title: Re: error msg?
Post by: dedndave on July 01, 2012, 05:10:32 AM
ok Jack
i think we have a handle on the problem   :P

Set INCLUDE=g:\jpsdhrs
Set PATH=g:\jpshdrs
Set PATH=g:\goasm.exe
GoAsm /l/b/c  MyProg.asm


when you use SET PATH, it replaces the old PATH variable
so - first, you set the PATH to one folder, then to another
also - you cannot set a file into the PATH - only folders

what you really want to do is add a folder to the PATH - not replace it entirely
you can do this by expanding the previous value for the PATH variable...
SET PATH=G:\jpshdrs;G:\goasm;%PATH%
i am not so sure that you really want the header files in the PATH, however

try this batch file...
Set INCLUDE=g:\jpsdhrs
Set PATH=g:\goasm;%PATH%
GoAsm /l/b/c  MyProg.asm
Title: Re: error msg?
Post by: dedndave on July 01, 2012, 05:46:03 AM
i just realized you may have another problem
that is...
the batch file you use to assemble is not in the PATH
this is why you have to place your ASM file in the same folder as the batch file

personally, i would set it up something like this
names without an extension are folders
names with an extension are files
follow the indentation to get an idea of the hierarchy...

G:\
--- GoAsm
------- Asm     (this is where you want to put your projects)
------- Bin     (this is where the GoAsm EXE files go - AND the batch files used to assemble/link)
------- Help    (this is where the CHM and HTML help files go)
------- Include (this is where the headers go, with all the sub-folders)

i would then modify the system-wide environment variables (My Computer/Properties/Advanced tab)
PATH - i would add G:\GoAsm\Bin to the current PATH variable
INCLUDE - i would create a variable and point it to G:\GoAsm\Include
Title: Re: error msg?
Post by: shankle on July 01, 2012, 07:05:02 AM
Thanks Dave,
Not sure I understand all of it but will give it a whirl.
Wish me luck...
Title: Re: error msg?
Post by: shankle on July 01, 2012, 10:49:47 PM
Status as of 7-1-2012.
MyProg.asm - #define LINKFILES,  #define jpshdrs,  #include g:\jpshdrs
MyProgbtch.bat - Set INCLUDE= g:\jpshdrs, Set PATH=g:\codejps,
                            GoAsm /l/b/c MyProg.asm

GoAsm folder (g) -
   bin          -  golink, Gorcjorg, GoAsm.exe, MyProgbtch.bat
   codejps  -  MyProg.asm
   gozips    -  Crimson editor svn286m, cedt-286m-setup.exe,
                     GoAsm.zip,  Gorcjorg.zip
   helpjps   -  forhelp.txt,  GoAsm.chm
   jpshdrs   -  (hopefully correct now. Before I had sub folders. Now only jpshdrs)
   files        -  cderr.h,  cedt.cmd,  cedt.exe,  cedt.mac,  cmdline.txt(empty)

I am afraid to mess with the environment variables Dave. It's different in Windows 7.
Can't it be made to work with the batch file?
Here is the ERROR message I get now:  ERROR - Could not open assembler source
file (MyProg.asm).  OBJ file not made.
Not trying to do the link as yet.
 
Title: Re: error msg?
Post by: dedndave on July 01, 2012, 10:57:39 PM
ok - let's take a safe approach   :biggrin:

when you open a console window and type:
PATH
and hit enter...
it will show you a list of folders, seperated by semicolons
find one of the folders that is already in the path
then, use that folder for your batch file
that way, when you type the name of the batch file, the OS can find it

then, we can use this for a batch file...
Set INCLUDE=g:\jpsdhrs
Set PATH=g:\goasm;%PATH%
GoAsm /l/b/c  MyProg.asm
Title: Re: error msg?
Post by: shankle on July 02, 2012, 12:45:34 AM
Hi Dave,
Got the Compile to output an ".obj" file.

MyProgbtch.bat - Set include=g:\jpshdrs,  Set PATH=g:\codejps,  GoAsm /l/b/c MyProg.asm
Here is what I did to get it to work. There is most likely a better way.

I moved MyProgbtch.bat and GoAsm.exe from the bin folder to the codejps folder.
In DOS I changed the c drive to the g drive: then did a g:cd \codejps
Executed MyProbtch.bat from the codejps folder and it compiled MyProg.asm
and output the MyProg.obj file.

From all this I'm expecting a the same hassle with the link process.

Just as a side my 10 ft dish survived Debbie and is working flawlessly.
If we get another one heading my way I'm going to take the dish down
and move it into the garage.
Thanks Dave for your patience.
Title: Re: error msg?
Post by: dedndave on July 02, 2012, 02:26:37 AM
well - at least you know it can work   :t

however, that sounds like a lot of typing to go through
i happened to think of another way...

you can create a desktop icon for the command prompt
the easiest way to do that is to right-click on the command prompt shortcut that is in the start menu
then click Copy
then right-click on the desktop and click Paste
that should copy the shortcut to the desktop

once you have a desktop shortcut for the command prompt,
you can modify it by right-clicking on it - then Properties
you can make it run a batch file for you on startup that will only apply to that shortcut
(i.e. it won't affect the command prompt shortcut that is in the start menu)

that batch file can be located in G:\GoAsm\Bin and can be something simple like this
@ECHO OFF
SET PATH=G:\GoAsm\Bin;%PATH%
SET INCLUDE=G:\GoAsm\Include
G:
CD \GoAsm\Asm


then you can put all your stuff back where it was

as an added touch, you can rename the desktop shortcut to "GoAsm Console" or something
Title: Re: error msg?
Post by: shankle on July 02, 2012, 03:09:06 AM
Status as of 7-1-2012.
Made a temp batch file for linking: - Set INCLUDE=g:\jpshdrs, Set PATH=g:\codejps,
GoLink /unused Kernel32.dll, User32.dll, Gdi32.dll, winspool.drv MyProg.obj
This of course gave errors. I thought all the Set commands with "jpshdrs" made the
header files available to the program and the linker. Obviously not.
Here are a few of the 40 or so items not defined in the object file - cbsize, hinstance, hwnd,
ShowWindowA, UpdateWindowA, msg, TransLateMessage, msg.wParam, GlobalAllocA.

I changed every API in the program from EX: ShowWindow to ShowWindowA. Maybe that's
not necessary.
Title: Re: error msg?
Post by: dedndave on July 02, 2012, 03:35:21 AM
yah - you should be able to take any one of Edgar's examples and make it fly   :t
Title: Re: error msg?
Post by: shankle on July 02, 2012, 11:08:05 PM
Compiles correctly.
At link time I get 3 error messages that the items are not found in the compile
or link: 
   cbsize,  CS_BYTEALIGNWINDOW,  hInstance
The headers are there to be used......

CS_BYTEALIGNWINDOW is used in WNDCLASSEX

cbsize is used in DOCINFO(A)

hInstance is used in .code/start but it isn't defined prior to that....????
  also in WNDPROC in a LOCAL hInst: HINSTANCE

Title: Re: error msg?
Post by: dedndave on July 03, 2012, 11:33:06 AM
maybe you can post the source ?
Title: Re: error msg?
Post by: wjr on July 04, 2012, 10:30:25 AM
Getting there... try cbSize - I think you need more there to, as in DOCINFO.cbSize, or whatever you named your instance of that structure (ex. MyDocInfo.cbSize). As for hInstance, you could define that as a global data variable. Not sure why CS_BYTEALIGNWINDOW shows up as not found since you seem to have the header files sorted out.
Title: Re: error msg?
Post by: shankle on July 04, 2012, 12:23:20 PM
My latest fumblings 7-3.

CS_BYTEALIGNWINDOW, FF_ROMAN, IDI_APPLICATION were solved by the following code:
  Styleid  db  'CS_BYTEALIGNWINDOW',0
  ffr         db  ' FF_ROMAN',0
  appid    db 'IDI_APPLICATION',0
These were fixed in WNDCLASSEX for EX:
     D[wc.style], addr styleid etc.

Appname  db 'MyProg.exe',0
These formats of DOCINFOA don't work:
  doci  DOCINFOa, [cbsize], [ Appname], null, null,0
  doci  DOCINFOa, cbsize, Appname, null, null,0
  doci  DOCINFOa, <cbsize, Appname, null, null,0>  ; this one worked in MASM32
All three gave an error message that doesn't make any sense:
   Misplaced Comma:-  , cbsize, Appname, null, null, 0

Thanks guys for the help.....


Title: Re: error msg?
Post by: wjr on July 04, 2012, 01:45:51 PM
Hmmm, fumblings is accurate... the compile errors will go away, but not really "solved" since your wc.style is actually now an address (and that address now points to a string, instead of a value). A more proper way to do something like this would be:

mov   D[wc.style], CS_BYTEALIGNWINDOW

doci   DOCINFO   <SIZEOF(DOCINFO), Appname, NULL, NULL, 0>

If this does not work for you, then your build process still has an issue with accessing the definitions in the header files. As for IDI_APPLICATION, that looks like an ID for an icon which should be defined in your resource RC file... that definition also needs to be in your ASM file (or in a common include file for the project).
Title: Re: error msg?
Post by: dedndave on July 04, 2012, 02:12:14 PM
IDI_APPLICATION is one of the standard windows icons
it should be defined in user32.h

my mistake - it should be defined in winuser.h
Title: Re: error msg?
Post by: shankle on July 04, 2012, 07:50:49 PM
Hi Guys,
To wjr,
mov D[wc.style], CS_BYTEALIGNWINDOW gives a compile error.
That is why I changed it to D[wd.style], addr stylied.
IDI_APPLICATION is also in WNDCLASSEX and making a zero string made
the compile error go away. FF_ROMAN is used in "CREATEFONT" and a
a zero based string made that error go away. Whether this is correct or
not I do not know but it eliminated the compile errors.
There is no resource file used in the program.
In reference to: doci DOCINFO <sizeof(Docinfo), Appname, NULL, NULL,0>
gave this error:  unexpected material <sizeof Docinfo), Appname, NULL, NULL, 0>
This also didn't work if I changed DOCINFO to DOCINFOA. 

To Dave,
I think I have my headers defined correctly of which one is winuser.h but as stated
above it gives compile errors in WNDCLASSEX. Both CS_BYTESALIGNWINDOW and
IDI_APPLICATION are defined in winuser.h. Question is why isn't it being picked up?

Title: Re: error msg?
Post by: dedndave on July 04, 2012, 10:49:22 PM
typically, i use IDI_APPLICATION like this
        INVOKE  LoadCursor,NULL,IDI_APPLICATION
        mov     hIcon,eax                               ;optional
        mov     wc.hIcon,eax
        mov     wc.hIconSm,eax


that's MASM syntax, of course   :P

it seems to me that LINKFILES should be defined, then windows.h should be included first
  #define  LINKFILES
  #include windows.h
  #include winuser.h

Title: Re: error msg?
Post by: shankle on July 05, 2012, 02:11:29 AM
Hi Dave,
I ASSUMED that LINKFILES brought in all the header files.
I compiled with: #INCLUDE windows.h and #INCLUDE winuser.h.
That gave an error. So I took out #INCLUDE winuser.h and that gave
a clean compile.
If I insert IDI_APPLICATION and CS_BYTEALIGNWINDOW in WNDCLASSEX
the linker rejects it. Had to put back "applid" and "styleid" to get it to work.
Don't understand why this is not picked up from "windows.h"

I know this goes against what you suggested prior but that suggestion gave
errors. To get around the errors my directory/folder setup is as follows:
  g:\codejps  - this contains GoAsm, GoLink, and all the header files.
So since GoAsm and the header files are all in the same folder it should be
able to access them. But I've been wrong before :(
Title: Re: error msg?
Post by: wjr on July 05, 2012, 04:18:33 AM
If the symbol LINKFILES is defined before including windows.h, the header files then use #dynamiclinkfile to place the names of system DLLs to import from into a "directive" section of the OBJ file for use by GoLink so that you do not need to specify these on the GoLink command line.

Including windows.h should be sufficient as it should include winuser.h and wingdi.h. However, the above DOCINFO unexpected material error (and FF_ROMAN) would seem to indicate that wingdi.h also is not getting included.

Yes, all in the same folder should work. If you do not get any "Could not open file:- #include FileName.h" errors, then perhaps a long shot, but make sure that you have not defined NOUSER and NOGDI before including windows.h.  Also, although those other changes are incorrect, if there are no compile errors, what do you get, if any, as GoLink errors?
Title: Re: error msg?
Post by: shankle on July 05, 2012, 05:37:35 AM
Thank you for replying WJR.
This is how LINKFILES is defined in MyProg:
  #define LINKFILES
  #include windows.h
  #define codejps

DOCINFO and FF_ROMAN seem to be behaving themselves now.
I do not have "NOUSER OR NOGDI" in the program.
I have changed CS_BYTEALIGNWINDOW and IDI_APPLICATION back
to the way they should be.

I can get a clean compile.
The linker blesses me with this error:
  The following symbols were not defined in the object file or files:-
  CS_BYTEALIGNWINDOW        IDI_APPLICATION
Title: Re: error msg?
Post by: dedndave on July 05, 2012, 07:20:13 AM
Quote from: shankle on July 05, 2012, 05:37:35 AM
This is how LINKFILES is defined in MyProg:
  #define LINKFILES
  #define windows.h

shouldn't that be
  #define  LINKFILES
  #include windows.h
Title: Re: error msg?
Post by: shankle on July 05, 2012, 07:40:01 AM
Hi Dave,
Looks like I can't get away with anything :biggrin:
Yes, will fix it.
Thanks
Title: Re: error msg?
Post by: wjr on July 05, 2012, 03:39:22 PM
If WinUser.h was somehow not being included, then you would have other errors (for example with WNDCLASSEX, RegisterClassEx, and WM_CREATE). So if it is just those two, check to see if they actually get defined in your WinUser.h file.
Title: Re: error msg?
Post by: shankle on July 05, 2012, 09:12:12 PM
Thank you WJR for responding.
In winuser.h I found:
    #define IDI_APPLICATION 32512 and  #define CS_BYTEALIGNWINDOW  0x2000
These switches are in winuser.h. Is it possible that winuser.h is not fully compatible
with Windows 7 Pro 32-bit?

My Wndclassex code:
   mov   D[wc.cbSize], SIZEOF WNDCLASSEX
   mov   D[wc.style], addr CS_BYTEALIGNWINDOW
   mov   D[wc.lpfnWndProc], OFFSET WndProc
   mov   D[wc.cbClsExtra], NULL
   mov   D[wc.cbWndExtra], NULL
   push  [hInst]
   pop   [wc.hInstance]
   invoke LoadIconA, NULL,addr IDI_APPLICATION
   mov   D[wc.hIcon], eax
    invoke LoadCursorA, NULL,[IDC_ARROW]
   mov   D[wc.hCursor], eax
   invoke CreateSolidBrush, [colorbk]          ; background color
    mov   D[hBrush], eax
   mov   D[wc.hbrBackground], eax
   mov   D[wc.lpszMenuName], NULL
   mov   D[wc.lpszClassName], OFFSET szDisplayName
   mov   D[wc.hIconSm], 0

LoadIcon     IDI_APPLICATION is defined in winuser.h but gives an error
Loadcursor  IDI_ARROW is NOT defined in winuser.h but gives NO error :(
mov   D[wc.style], addr CS_BYTEALIGNWINDOW is defined in winuser.h but gives an error.

Switches used in winuser.h
WINNT4 = Used only with Windows NT version 4 (note: may not be compatible with other versions)
WIN9X = Used only with Windows 95/98/ME (note: may not be compatible with other versions)
WINCE = Used only with Windows CE (note: may not be compatible with other versions)
WIN64 = For use only with a 64 bit Windows
UNICODE = Use UNICODE versions

All the structs have been found but one.
In winuser.h the RECT struct is defined as follows:
     #IFNDEF  RECT STRUCT  left dd ?  top dd  ?  right dd ?   bottom dd ? ENDS  rc RECT
I had to code this in MY Progie to get rid of errors.
Title: Re: error msg?
Post by: wjr on July 06, 2012, 10:53:26 AM
The header files have been around for a while on the 32-bit side, so I would say no compatibility issues. Ahhh, that would do it... you do seem to have the header files working now, so if you have difficulties that you can not resolve on your own, posting a bit source code will make things Go much quicker. Corrected lines follow:

mov   D[wc.style], CS_BYTEALIGNWINDOW
invoke LoadIcon, NULL, IDI_APPLICATION
invoke LoadCursor, NULL, IDC_ARROW

Also, the header files take care of the ANSI / UNICODE API naming, so you usually do not need to specify the A version.
Title: Re: error msg?
Post by: shankle on July 07, 2012, 07:41:29 AM
Thanks WJR,
The errors in the WNDCLASSEX struct are now history.

Still have the RECT struct coded in the program.
Without it I get errors.

Working on some other link errors which I am trying to solve.
Title: Re: error msg?
Post by: shankle on July 09, 2012, 10:32:42 PM
Down to 3 errors at link time.
  rc,  dwvalue and hInst

RC with RECT
dwValue with dwtoa

I have the RECT struct defined in the program and it is giving an error
RC.dll not found. It doesn't seem to call any headers.
If I take the RECT Struct  of the program I get errors.

Title: Re: error msg?
Post by: dedndave on July 10, 2012, 12:09:37 AM
Quote from: shankle on July 09, 2012, 10:32:42 PM
Down to 3 errors at link time.
  rc,  dwvalue and hInst

RC with RECT
dwValue with dwtoa
dwvalue is not the same as dwValue   :P

RC.dll may be the resource compiler - not the RECT struct

WJR = Wayne J. Radburn   :t
Title: Re: error msg?
Post by: wjr on July 10, 2012, 12:52:31 AM
Let the header files define RECT. There would appear to be an "RC.dll" in your source (not the same as rc.dll), but dll is not a member of RECT, so that should be easy to find and fix.
Title: Re: error msg?
Post by: shankle on July 10, 2012, 12:57:24 AM
To Dave,
Yep - a typo - dwValue

To WJR,
I let the header files reference RECT.
I have included in the program "windows.h and Mr. Hansen's header files".
There is NO reference in the program to "RC.DLL".
Here is the error I am getting at link time:
   Could not open an input file (RCC.DLL) needed for forced dll or  import
    by ordinal.
Thanks fellows
Title: Re: error msg?
Post by: wjr on July 10, 2012, 01:46:05 AM
Assuming you are simply trying to use a RECT called RC, the "forced dll" part would lead me to believe that in your source you have a reference to "RC:" (or "RCC:") with a colon (where one is not needed, or instead of a period).
Title: Re: error msg?
Post by: shankle on July 10, 2012, 02:38:58 AM
Got a clean compile and link.
When I click on MyProg.exe it blinks and nothing happens.
Major digging now. Have a test msg in WM_PRINT and it never gets there.
Will put a test msg in WM_CREATE  to see if it gets there.

Seems I am confused in GoAsm as to when to put in a Frame/Local
statement for ex: rc:RECT or rc?       
   
Will do more digging to see if I can figure this one out.
Title: Re: error msg?
Post by: dedndave on July 10, 2012, 02:48:55 AM
Local msg, MSG, hWnd, hBrush, rc, wc_WNDCLASSEXA, cc:codecode

that's a bit of a mess, Jack   :biggrin:

local's need to be typed
MSG is a structure (which is a sort of a type)
try this
    LOCAL msg:MSG, hWnd:HWND, hBrush:HBRUSH, wc:WNDCLASSEX, cc:codecode
i am not sure about the last one
i assume you have defined the type (or structure) "codecode" somewhere previously in the source

MSG and WNDCLASSEX are structures that should be defined in the include files
HWND and HBRUSH are DWORD types that should be defined in the include files
Title: Re: error msg?
Post by: shankle on July 11, 2012, 02:50:01 AM
In the testing phase of MyProg.exe I got this error message:
  " MyProg.exe has stopped working"
No 1st screen or anything. I put  messagebox  code right after the START
and it did not execute. So I assume  something else is happening.
     
.code
start:
;   test begin
;TM3              db   'at start',0
      invoke MessageBox, NULL,[TM3],[TM3],MB_YESNO     
       cmp eax,MB_YESNO
        je > Twrite
Twrite:
;   test end

   invoke GetModuleHandleA, NULL
   mov    [hInstance],eax
   invoke GetCommandLine
   invoke WinMain
   invoke ExitProcess,eax

WinMain:
    FRAME hInst,hPrevInst,CmdLine,CmdShow,hInstance;
   LOCAL msg,MSG,hWnd,hBrush,rc:RECT,wc:WNDCLASSEXA;,cc:codecode       

   mov   D[wc.cbSize], SIZEOF WNDCLASSEXA
   mov   D[wc.style], CS_BYTEALIGNWINDOW    
   mov   D[wc.lpfnWndProc], OFFSET WndProc
   mov   D[wc.cbClsExtra], NULL
   mov   D[wc.cbWndExtra], NULL
   push  [hInst]
   pop   [wc.hInstance]
   invoke LoadIcon, NULL,IDI_APPLICATION
   mov   D[wc.hIcon], eax
    invoke LoadCursor, NULL,IDC_ARROW
   mov   D[wc.hCursor], eax
   invoke CreateSolidBrush, [colorbk]          ; background color
    mov   D[hBrush], eax
   mov   D[wc.hbrBackground], eax
   mov   D[wc.lpszMenuName], NULL
   mov   D[wc.lpszClassName], OFFSET szDisplayName
   mov   D[wc.hIconSm], 0

   invoke RegisterClassExA, addr wc
    invoke SystemParametersInfoA, SPI_GETWORKAREA,0,addr rc,0       
     mov eax,[rc.left]
     mov [holdleft], eax
     mov eax,[rc.right]
     mov [holdright],eax
     mov eax,[rc.bottom]
     mov [holdbottom],eax
     mov eax,[rc.top]
     mov [holdtop],eax
     push edx               
     push ebx
     xor edx,edx     
     mov eax,[holdright]     
     mov ebx,2               
     div ebx
     mov [savemiddleofX],eax   
     pop ebx
     pop edx
   INVOKE CreateWindowExA, NULL,addr szDisplayName,addr AppName,\
           WS_OVERLAPPEDWINDOW,[rc.left],[rc.top],[rc.right],\
           [rc.bottom],NULL,NULL,[hInst],NULL       
      mov   [hWnd],eax     
 
   INVOKE ShowWindow, [hWnd], SW_SHOWNORMAL
   INVOKE UpdateWindow, [hWnd]

      .StartLoop
          INVOKE GetMessageA, addr msg,NULL,0,0
          cmp eax,0
          je >.ExitLoop
          INVOKE TranslateMessage, addr MSG
          INVOKE DispatchMessageA, addr MSG
          jmp .StartLoop
       .ExitLoop
       mov eax,[MSG.wParam]
          ret           
       ENDF
   
Title: Re: error msg?
Post by: dedndave on July 11, 2012, 03:38:30 AM
try this program, Jack
.data
TM3              db   'at start',0
.code
start:
      invoke MessageBox, NULL,TM3,TM3,MB_YESNO
      invoke ExitProcess,0
end start
Title: Re: error msg?
Post by: wjr on July 11, 2012, 04:21:00 AM
GoAsm syntax differs a bit from MASM for an address:

INVOKE MessageBox, NULL, ADDR TM3, ADDR TM3, MB_YESNO

Going further, you will need Dave's above corrections for LOCAL and the
WinMain FRAME should have 4 parameters:

WinMain:
FRAME hInst, hPrevInst, CmdLine, CmdShow


More importantly, when you call WinMain, you need to supply those arguments to the call, something like:

INVOKE GetCommandLine
mov [pCmdLine],eax

INVOKE WinMain, [hInstance], NULL, [pCmdLine], SW_SHOWDEFAULT


Also, in your message loop, change MSG (structure template) to msg (your locally defined instance of that structure).
Title: Re: error msg?
Post by: dedndave on July 11, 2012, 05:05:38 AM
hi Wayne
i thought GoAsm syntax would yield the address of TM3 for "TM3"
and the contents at the address for "[TM3]"
Title: Re: error msg?
Post by: shankle on July 11, 2012, 05:46:58 AM
Some progress.
I did get my info msg at START. Then moved it to WinMain and nothing.

To Dave- codecode is a struct I defined,  TM3 is a msg defined in the data section.

To WJR - I changed to LOCAL statement to the following:
   Local msg:MSG, hWnd:HWND, hBrush:HBRUSH, rc:RECT, wc:WNDCLASSEX, cc:codecode
Now I get the following error:  "data type given in local data declaration not recognized:-
  HWND"
I changed MSG to msg as directed in your last statement.
Here is the error msg I get: "The following symbol was not defined in the object file
or files:- msg.wParam"

Guess I'm confusing the Local statement with the Frame statement?
Title: Re: error msg?
Post by: dedndave on July 11, 2012, 06:28:58 AM
if HWND is not defined in the include files, it probably should be
if one of the DWORD typedef's is missing, you can just use DWORD...
    Local   hWnd:DWORD

however, it may be that the name "hWnd" is used elsewhere in a visible scope

it might be easier if you'd attach the source, then Wayne or i could step through and clean it up in one pass

QuoteI changed MSG to msg as directed in your last statement.
Here is the error msg I get: "The following symbol was not defined in the object file
or files:- msg.wParam"

this problem may be related to the first
if it doesn't resolve all of the LOCAL declarations, it may not create any of them
Title: Re: error msg?
Post by: wjr on July 11, 2012, 06:45:10 AM
Correction, the syntax difference is more on the memory addressing side which requires the square brackets for the contents at the address. For the address itself though, ADDR or OFFSET (either one for GoAsm, some differences between them for MASM) is still required in code (but not necessary as part of a data declaration).

A very quick look and I didn't see HWND defined in the header files, in WinDef.h at least, so you can also use HANDLE instead. Not sure why msg does not work for you if rc and wc do...
Title: Re: error msg?
Post by: shankle on July 11, 2012, 07:02:19 AM
Thanks guys.
Made some progress and am now into the WM_CREATE.

       invoke  GlobalLock, eax      
       mov       [pinf04],eax      t
       mov       ebx,eax      
       push  ebx
        invoke  EnumPrintersA, PRINTER_ENUM_LOCAL,NULL,4,[pinf04],\
                                [dwNeeded],[dwNeeded],[dwReturned]
                 
        pop ebx                                                          
        invoke  CreateDC, NULL,[ebx+PRINTER_INFO_4.pPrinterName],NULL,NULL

The offending instruction is the CreateDC. The ones above it worked.
Most likely it is the ebx+PRINTER_INFO_4.pPrinterName


Title: Re: error msg?
Post by: dedndave on July 11, 2012, 12:04:32 PM
see if this works
       invoke  GlobalLock, eax     
       mov       [pinf04],eax      t
       mov       ebx,eax     
        invoke  EnumPrintersA, PRINTER_ENUM_LOCAL,NULL,4,eax,\
                                [dwNeeded],[dwNeeded],[dwReturned]
        lea     eax,[ebx+PRINTER_INFO_4.pPrinterName]
        invoke  CreateDC, NULL,eax,NULL,NULL
Title: Re: error msg?
Post by: shankle on July 11, 2012, 01:10:05 PM
Hi Dave.
The lea seemed to solve the problem. More testing will tell for sure
Title: Re: error msg?
Post by: jj2007 on July 11, 2012, 03:30:16 PM
Masm can do the lea for you:

invoke CreateDC, NULL, addr [ebx+PRINTER_INFO_4.pPrinterName], NULL, NULL
Title: Re: error msg?
Post by: shankle on July 11, 2012, 09:41:47 PM
Hi JJ2007 and thanks for the reply.
GoAsm gives an error with your suggestion.

Now the ShowWindow gives an error in GoAsm.
It works fine in Masm32.
The CreateWindowEXA works.

hWnd    dd  0

   INVOKE CreateWindowExA, NULL,addr szDisplayName,addr AppName,\
           WS_OVERLAPPEDWINDOW,[rc.left],[rc.top],[rc.right],\
           [rc.bottom],NULL,NULL,[hInst],NULL       
      mov   [hWnd],eax     
 
   INVOKE ShowWindow, [hWnd], SW_SHOWNORMAL
   INVOKE UpdateWindow, [hWnd]
Title: Re: error msg?
Post by: wjr on July 12, 2012, 02:57:34 AM
Sorry, as you most likely found out, LOCAL hWnd:DWORD and LOCAL hWnd:HANDLE do not work. The corrections for these would be LOCAL hWnd:D and LOCAL hWnd:%HANDLE.

However, since for a 32-bit application a DWORD is the default, this can be simplified to LOCAL hWnd which is better if you plan on going to 64-bit where QWORD is the default (the %HANDLE definition in the header files would also make this switch).

If you get an error, please specify the GoAsm or GoLink error message. I do not get an error using what you originally had for your CreateDC call. If you used a global variable for hWnd, I do not see how that would give an error. Given that you have had some problems with hInst, although CreateWindowExA works, does it return NULL? This is an error condition that you should generally check for, since ShowWindow and the rest are not going to work.

Title: Re: error msg?
Post by: shankle on July 12, 2012, 10:27:56 PM
In my test the CreateWindowEX tests as BAD.
This is the same code I use in my MASM32 version.
Regardless of the test the CreateWindowEX does not work.
No error message from GoAsm but a Window message saying the program
has stopped working. cc:codecode is a struct I defined.

WinMain:
    FRAME hInst,hPrevInst,CmdLine,CmdShow
   LOCAL msg:MSG,rc:RECT,wc:WNDCLASSEXA,cc:codecode,hWnd
; more code which is already mentioned in a prior mesage               

   INVOKE CreateWindowEx, NULL,addr szDisplayName,addr AppName,\
           WS_OVERLAPPEDWINDOW,[rc.left],[rc.top],[rc.right],\
           [rc.bottom],NULL,NULL,[hInst],NULL       
      mov   [hWnd],eax 
     
;test code begin
;szText             db   ' executed correctly',0
;szText2           db   ' is bad',0
;szCaption       db   'TRUE',0
;szCaption2     db   'FALSE',0
       pusha
          cmp D[eax], 0     ; success
           je >         
             invoke MessageBox, NULL, ADDR szText, ADDR szCaption, MB_OK
           jmp >out1
:             
             invoke MessageBox, NULL, addr szText2, addr szCaption2, MB_OK
out1:             
       popa
;test code end         
 
   INVOKE ShowWindow, [hWnd], SW_SHOWNORMAL
   INVOKE UpdateWindow, [hWnd]
   
; message loop here also mentioned in a prior message   

 
Title: Re: error msg?
Post by: dedndave on July 12, 2012, 11:06:13 PM
rc.right and rc.bottom are screen coordinates
the parameters should be width and height

another potential problem...
the window handle is generally stored in a global variable, rather than a local one
this may not be a problem, if the code is written to always use a local value
Title: Re: error msg?
Post by: shankle on July 13, 2012, 01:06:28 AM
Hi Dave,
The rc.bottom/rc.right are part of the RECT struct.
This worked fine in my MASM32 program.

If anything I would suspect  the trouble is caused by how I have defined  hWnd.
As far as I know I am using a Local definition of hWnd.
This also worked in the MASM32 version.

In answer to WJR the CreateWindowEX does return 0/NULL .
Question is why and what caused it?

Title: Re: error msg?
Post by: dedndave on July 13, 2012, 02:22:53 AM
what value does the WM_CREATE code in WndProc return in EAX ???
WM_CREATE should return 0 to continue creation of the window
if WM_CREATE returns -1, window creation ceases and CreateWindowEx returns 0

also - the message loop must be working properly for WM_CREATE to succeed

at any rate - you can use GetLastError for a general idea of what caused the problem
i am guessing - invalid parameter   :P
or maybe - class not found

also...
window creation causes a myriad of other messages to be sent to WndProc
like getminmaxinfo, paint, ncpaint, geticon - a bunch of em
be sure the structure of WndProc allows unhandled messages to pass to DefWindowProc   :t
Title: Re: error msg?
Post by: wjr on July 13, 2012, 03:09:03 AM
The local hWnd looks good now. Before diving into other messages, to be on the safe side, did you fix your INVOKE WinMain as suggested back in Reply #65? If not, your value in [hInst] will be wrong causing CreateWindowEx to fail.
Title: Re: error msg?
Post by: shankle on July 13, 2012, 04:03:51 AM
I did make the changes requested as seen below:

pCmdline         dd       0

   invoke GetModuleHandleA, NULL
   mov    [hInstance],eax
   invoke GetCommandLine
        mov [pCmdline], eax      
   invoke WinMain, [hInstance],NULL,[pCmdline],SW_SHOWDEFAULT
   invoke ExitProcess,eax

WinMain:
    FRAME hInst,hPrevInst,CmdLine,CmdShow
   LOCAL msg:MSG,rc:RECT,wc:WNDCLASSEXA,cc:codecode,hWnd             
Title: Re: error msg?
Post by: dedndave on July 13, 2012, 05:43:26 AM
       pusha
;
;
;
       popa

PUSHA and POPA push and pop words !!!
use PUSHAD and POPAD to push and pop dword register values

    INVOKE CreateWindowEx, NULL,addr szDisplayName,addr AppName,\
           WS_OVERLAPPEDWINDOW,[rc.left],[rc.top],[rc.right],\
           [rc.bottom],NULL,NULL,[hInst],NULL     
      mov   [hWnd],eax
.if !eax
invoke GetLastError
invoke MessageBox,0,uhex$(eax),0,0
invoke ExitProcess,0
.endif
Title: Re: error msg?
Post by: dedndave on July 13, 2012, 05:51:19 AM
this code will display the error as a string, rather than a number   :biggrin:

    INVOKE  CreateWindowEx, NULL,addr szDisplayName,addr AppName,\
            WS_OVERLAPPEDWINDOW,[rc.left],[rc.top],[rc.right],\
            [rc.bottom],NULL,NULL,[hInst],NULL     
    mov     [hWnd],eax
    .if !eax
        INVOKE  GetLastError
        sub     esp,512
        xor     ecx,ecx
        mov     edx,esp
        INVOKE  FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,ecx,eax,ecx,edx,512,ecx
        mov     edx,esp
        xor     ecx,ecx
        INVOKE  MessageBox,ecx,edx,ecx,ecx
        add     esp,512
        INVOKE  ExitProcess,0
    .endif



Title: Re: error msg?
Post by: shankle on July 13, 2012, 08:55:50 AM
Hi Dave,
The "IF" statement in your last message  has to be changed to GoAsm format.
I have no idea how to change "!eax" to GoAsm format. I interpret it as not eax.
Otherwise I would try it.
Title: Re: error msg?
Post by: dedndave on July 13, 2012, 08:57:56 AM
.if !eax means "if not eax" or "if eax is 0"
    INVOKE  CreateWindowEx, NULL,addr szDisplayName,addr AppName,\
            WS_OVERLAPPEDWINDOW,[rc.left],[rc.top],[rc.right],\
            [rc.bottom],NULL,NULL,[hInst],NULL     
    mov     [hWnd],eax
    or      eax,eax
    jnz     around
        INVOKE  GetLastError
        sub     esp,512
        xor     ecx,ecx
        mov     edx,esp
        INVOKE  FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,ecx,eax,ecx,edx,512,ecx
        mov     edx,esp
        xor     ecx,ecx
        INVOKE  MessageBox,ecx,edx,ecx,ecx
        add     esp,512
        INVOKE  ExitProcess,0
around:
Title: Re: error msg?
Post by: shankle on July 13, 2012, 10:52:42 PM
Hi Dave,
Added your code with the small change to conform to GoAsm format.

    cmp D[eax],0
      jnz > around

Maybe this sequence might shed some light on the problem.
I have message boxes at Start, just before CreatWindowEX in winmain and
at the end of WM_CREATE. I have Dave's error code just after the CREATEWINDOWEX.
When I run the program these messagebox messages occur in this order:
Start, WinMain, WM_CREATE, BOMB. The program is supposed to return to
CreatWindowEX after WM_CREATE. Then Dave's error code check would execute
if an error occurred. Instead a windows message occurs stating that the program
has stopped working.
Title: Re: error msg?
Post by: dedndave on July 14, 2012, 02:04:37 AM
QuoteInstead a windows message occurs stating that the program has stopped working.

i hope it says more than that   :P

i would have to guess there is a problem with WndProc
but - it could be the message loop, as well

make sure WndProc is set up correctly, in general:
EBX, EBP, ESI, EDI are preserved (or not destroyed)
the routine pops 4 dword parms when it returns (RET 16)
unhandled messages invoke DefWindowProc and return it's value from EAX

you could put a temporary version of WndProc in there that handles a minimal number of messages
for example - if it just handles WM_CLOSE and WM_DESTROY
at least you can see if a window appears
in fact, all you need is DefWindowProc and a RET (close is nice, though)
    INVOKE  DefWindowProc,hWnd,uMsg,wParam,lParam
    ret


you might disassemble the code
sometimes, the problem glares at you from the disassembled code, while the source format hides it

attach the EXE to your next post - i'll have a look
Title: Re: error msg?
Post by: Ryan on July 14, 2012, 04:15:31 AM
Correct me if I'm wrong, but you need to handle WM_DESTROY with a PostQuitMessage, no?  Without it the window will close, but the process will remain running.  DefWindowProc does not do it.
Title: Re: error msg?
Post by: dedndave on July 14, 2012, 05:00:16 AM
yes - that's what i say
but - you can assemble and run without it - then use the task manager to close it

the idea here is a one-time temporary test to see if things are put together right
Title: Re: error msg?
Post by: shankle on July 14, 2012, 05:55:11 AM
; MASM32 This code is working in MASM32
WndProc PROC  hWnd:HWND, iMsg:UINT, wParam:WPARAM, lParam:LPARAM
       mov   eax,iMsg
       .IF eax==WM_CREATE
       
;-------------------------
; This code does not work in GoAsm
WndProc FRAME  hWnd,iMsg,wParam,lParam       
;   test begin
;TM8              db   'begin of wndproc',0
      pushad
      invoke MessageBox, NULL,addr TM8,addr TM8,MB_YESNO     
      popad
;   test end
      mov   eax,[iMsg]
      uses ebx,edi,esi
      Local hMemory,stm:SYSTEMTIME,ps,hdc,hdcPrn

;.WM_CREATE
        cmp D[eax],WM_CREATE
         jne >>.WM_CHAR         
; ----------------------         
        cmp D[eax],WM_CHAR 
        jne >>.WM_PAINT     
;--------------------------       
.WM_PAINT
        cmp D[eax],WM_PAINT 
        jne >>.WM_DESTROY
;------------------------------         
.WM_DESTROY         
        cmp D[eax],WM_DESTROY 
         jne >

What happens is it never gets to WM_Create.
Then gives windows error message: MyProg has stopped working.

If I take my test message out then it gets to WM_create and then gives
a Windows error message : MyProg has stopped working.

If I change cmp D[eax],WM_CREATE to cmp D[iMsg], WM_Create then
it goes into a loop in Wndproc. Have to power down the puter to get out if it.
Title: Re: error msg?
Post by: wjr on July 14, 2012, 08:02:38 AM
Getting there... the code for your procedure should be placed after USES and LOCAL (not sure if your ps should be ps:PAINTSTRUCT). Once you have the value of the message in eax, for the comparisons use eax and not D[eax].

WndProc FRAME hWnd,iMsg,wParam,lParam       
USES ebx,edi,esi
LOCAL hMemory,stm:SYSTEMTIME,ps,hdc,hdcPrn

mov eax,[iMsg]
.WM_CREATE
cmp eax,WM_CREATE
jne >>.WM_CHAR


When you tried cmp D[iMsg], WM_CREATE that was actually correct. Unfortunately, that means there are still some corrections after this point to track down...
Title: Re: error msg?
Post by: satpro on July 14, 2012, 12:54:06 PM

shankle,
I noticed a few things.  GoAsm doesn't use if/then/else syntax.  It is only for conditional assembly.  Using a combination of compares and/or testing flags is the way you have to go.  Anyway, it'll keep you much more focused on the state of the machine.  Knowing the zero, carry, and sign flags inside-out is a must.  Also, please read the GoAsm manual section on stack frames/local variables.  There is a specific order, e.g. FRAME, USES, LOCAL, CODE,RET,ENDF / ENDU.
I tried to see if I could fix your WndProc--it was just too much for me--sorry.  It needs to be simpler--much simpler.  So, I've included the bare bones of one I use.  It is also originally from the manual.  I hope I didn't rip too much out, but it should basically work for you.  The "message compares" use a table with the messages and the addresses of the message handler routines.  If you want to be good at this you'll start using tables for much of what you do, especially math.  Tables are magnitudes faster than anything else because you can branch on flags--and they will always work better than a bunch of slow, sloppy compares that you find in if/then statements.  Sometimes (multiplication) tables can be big.  But so what?  Always better than slow.  And you'll hear guys argue against that point.  They probably didn't program 1 mHz 8-bit computers in the 70s & 80s, when every byte (and every cycle) mattered.  Good assembly language is an art, no doubt about it.  That stuff still matters.  So, be an artist.  Let the "C" guys rely on the fact they have (and need) a 3 gHz machine to make complicated stuff fly.
About saving registers:  if you don't modify them in a procedure don't bother to push/pop them.  Blindly pushing all the registers makes for slow code.  Eventually you'll even start to notice the difference in execution speed.  But, if you "use" them, then by all means you should "USES" them.  That's the good thing about "USES".  You just look through that particular procedure and code a "USES reg,reg,reg" etc for each register used IN THAT PROCEDURE.  The exception is if you return something in, say eax.  You'll wind up losing it if you "USES" it  ;) .  (Did that on purpose)
So, I hope you can use this.  Study how that message table works.  It's old-school, quality assembly--and it's FAST.  And simple.  It's Jeremy Gordon code...


CONST SECTION


;   ******************** Window message table **********************
;
MESSAGES DD WM_CREATE,    CREATE       ;the message then the code address
         DD WM_DESTROY,   DESTROY
         DD WM_PAINT,         PAINT
         DD WM_KEYDOWN,  KEYDOWN
         DD WM_TIMER,        TIMER


CODE SECTION

WndProc:
FRAME hwnd, Msg, wParam, lParam     ;establish stack frame, get params


;--------------------------------------
;FIND THE A MESSAGE WE'RE INTERESTED IN
;--------------------------------------
mov eax, [Msg]                                 ;get in eax message sent by Windows
mov ecx, SIZEOF MESSAGES/8        ;get number of messages to look at
mov edx, ADDR MESSAGES


P1:
dec ecx                                             ;count down to -1
js >.notfound                                     ;if = -1 then call default win procedure


cmp [edx+ecx*8],eax                        ;check table if entry is correct message
jnz <P1                                            ;no, so loop back for next table entry


call [edx+ecx*8+4]                           ;call the correct procedure for the message
jnc >.exit


;----------------------------------------
;NO MATCH, SO PASS PARAMS BACK TO WINDOWS
;USE DEFAULT WINDOWS PROCEDURE
;----------------------------------------
.notfound
push [lParam]
push [wParam]
push [Msg]
push [hwnd]
call DefWindowProc


;------------------------------
;DESTROY STACK FRAME, EXIT BACK TO WINDOWS HERE
;------------------------------
.exit
ret
ENDF


;_________________________________________________________________________
;_________________________________________________________________________


PAINT:                      ;       RE-DRAW WINDOW
USEDATA WndProc                ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi    ;only save registers that you use in this procedure
;-------------------------------------------------------------


;---------------
;CALL BEGINPAINT
;---------------
invoke BeginPaint, [hwnd], ADDR ps
mov [hdc], eax


;updating/refreshing the window goes here


;-------------
;CALL ENDPAINT
;-------------
invoke EndPaint, [hwnd], ADDR ps


;---------
;EXIT HERE
;---------
xor eax,eax                 ;return not carry and eax = 0
ret
ENDU                        ;finished using parameters sent to WndProc


;_________________________________________________________________________
;_________________________________________________________________________


CREATE:                     ;       PROGRAM INITIALIZATION
USEDATA WndProc                  ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi      ;only save registers that you use in this procedure
;-------------------------------------------------------------



;program init goes here


;---------
;EXIT HERE
;---------
xor eax,eax                 ;return not carry and eax = 0
ret
ENDU                        ;finished using parameters sent to WndProc


;_________________________________________________________________________
;_________________________________________________________________________


DESTROY:                    ;       PROGRAM CLEAN-UP
USEDATA WndProc                            ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi                ;only save registers that you use in this procedure
;-------------------------------------------------------------


invoke PostQuitMessage, NULL            ;kill the application


;---------
;EXIT HERE
;---------
xor eax,eax                 ;return not carry and eax = 0
ret
ENDU                        ;finished using parameters sent to WndProc


;_________________________________________________________________________
;_________________________________________________________________________


KEYDOWN:                    ;       PROCESS KEYPRESSES
USEDATA WndProc                            ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi                ;only save registers that you use in this procedure
;-------------------------------------------------------------




mov eax, [wParam]


;----------------------
;COMPARE TO ESCAPE KEY?
;----------------------
cmp eax, VK_ESCAPE 
jne >E9


invoke PostQuitMessage, NULL            ;kill the application


;---------
;EXIT HERE
;---------
E9:
xor eax,eax                 ;return not carry and eax = 0
ret
ENDU                        ;finished using parameters sent to WndProc


;_________________________________________________________________________
;_________________________________________________________________________




TIMER:                    ;       PROCESS TIMERS
USEDATA WndProc                                 ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi                ;only save registers that you use in this procedure
;-------------------------------------------------------------


;code if you process timers
;I always use timer proc outside the window


;---------
;EXIT HERE
;---------
xor eax,eax                 ;return not carry and eax = 0
ret
ENDU                        ;finished using parameters sent to WndProc



Title: Re: error msg?
Post by: jj2007 on July 14, 2012, 06:24:46 PM
Quote from: satpro on July 14, 2012, 12:54:06 PM
Blindly pushing all the registers makes for slow code.

Sounds familiar (http://masm32.com/board/index.php?topic=250.msg1314#msg1314) :biggrin:
Title: Re: error msg?
Post by: dedndave on July 14, 2012, 06:26:53 PM
yah - but you're bloating CPU time that might be used for some other process, nonetheless
Title: Re: error msg?
Post by: satpro on July 14, 2012, 10:47:31 PM
Quote from: jj2007 on July 14, 2012, 06:24:46 PM
Quote from: satpro on July 14, 2012, 12:54:06 PM
Blindly pushing all the registers makes for slow code.

Sounds familiar (http://masm32.com/board/index.php?topic=250.msg1314#msg1314) :biggrin:
And it wasn't that long ago, was it?  I realized (while) you all were having that discussion the answer was basically rule #1 in assembly:  "Preserve that and only that which you use."  It's actually quite simple, and the same whether we're talking 65x, 68x, or x86.  At the time I thought there might be some hard and fast rule among the hard-cores here, so I decided to ask.  Turns out there wasn't.  My simple question turned into quite a lengthy discussion, didn't it?
Title: Re: error msg?
Post by: jj2007 on July 14, 2012, 11:08:23 PM
There is no need for a lengthy discussion, there is a need for empiric evidence instead of religious beliefs. Tell me by how much % a "uses esi edi ebx" slows down your proggie, and I'll keep my mouth shut.
Title: Re: error msg?
Post by: satpro on July 15, 2012, 07:31:18 AM
Well, there was a lengthy discussion about the topic, and quite a few of us were part of it.  If you add six (or more) needless cycles (and bytes) to every procedure, especially the Window Procedure, running over and over, it's not just a percentage--it's a hard count.  That stuff adds up.  Maybe some guy is still using an old laptop with 1 cpu @ 800 mHz, trying to play music in the background.  That style of programming will cost HIM up to 16x.  You don't think he'll notice?


So, save those registers for no reason.  Freedom of expression--I don't imagine anyone will stand in your way.  But if we are talking assembly language technique (religious belief?) then it's a different story, especially for someone like shankle who might be new to this and only wants to learn good, solid programming.  Yes, of course it's safe to push ebx, esi, and edi, or to push all of them for that matter.  It's also borderline sloppy.  Why do it if it's not necessary?


I just hope it's not because  "... otherwise Hutch & me & a few others will eat you alive :greensml:  ."   ->Incidentally, Hutch excluded his name from that line...he put it this way:

" :biggrin:

This is actually BAD advice."
Title: Re: error msg?
Post by: jj2007 on July 15, 2012, 07:37:57 AM
Quote from: satpro on July 15, 2012, 07:31:18 AMit's not just a percentage--it's a hard count.

Show us. Express it in nanoseconds, cycles, percent, whatever, but quantify the "hard count". Show us how much the guy with the 800 MHz CPU will suffer.

(no need to indulge in precision, a back-of-the-envelope formula will be sufficient)
Title: Re: error msg?
Post by: satpro on July 15, 2012, 07:45:03 AM
I made my point.


But ok... against today's 4x cpu, 3.2 gHz machine.  BTW, how does one expect nanoseconds and cycles, yet precision is not necessary?
Title: Re: error msg?
Post by: jj2007 on July 15, 2012, 08:25:46 AM
Quote from: satpro on July 15, 2012, 07:45:03 AMBTW, how does one expect nanoseconds and cycles, yet precision is not necessary?

jj: (http://masm32.com/board/index.php?topic=250.msg1314#msg1314) "Most [messages] are WM_MOUSEMOVE - a particularly fast one with only 600 cycles. 3 push/pop pairs delay WM_MOUSEMOVE by 0.00008 milliseconds - how significant is that delay?"

That is admittedly not very precise, it could be 0.00007 milliseconds or 0.00009 milliseconds, but it still holds much more information than a bold "unnecessary pushing costs a lot of CPU power" statement. Remember your CPU does approx. 2500000000 cycles per second. If you want to get it sweating, you need something much more serious than a little pushin' and poppin' in an idle WndProc, e.g.
xor ecx, ecx
@@: dec ecx
  jne @B
is a good exercise for your lazy CPU :bgrin:

I understand that you like the idea of being a hardcore assembly programmer, but what you claim is simply not relevant in a WndProc, because a) these messages don't get called a Million times per second and b) the extra 3 cycles are statistical noise when def-processing the message takes many hundreds of cycles.

Your line of reasoning does hold in an innermost loop which gets called a Million times (and yes, I mean a Million, not less). And of course, you would never call a subproc from within an innermost loop, so the push & pop argument is completely irrelevant anyway.
Title: Re: error msg?
Post by: satpro on July 15, 2012, 09:09:52 AM
jj,


I get where you're coming from, and for the most part assembly corrects all of C/C++s speed issues, but I really want to get back to shankle's problems learning GoAsm.  He deserves a fair shot at this.  I think I was responding initially to the sarcasm aimed at me regarding the question I asked a couple of weeks ago just looking for an informed opinion about register preservation.  I'm not some newbie--quite the opposite.  Just never really heard anyone talking about it before.  So I asked.


If you want to make the cpu sweat, simply switch over to PeekMessage.  That'll do it.  As an aside, I still have one of those 800 mHz laptops that I use when I'm away from this thing and my wife's is in her hands.  That machine sweats everything--except for well-written assembly programs like qeditor or GoAsm.  I can literally see mouse activity in the task manager.  So yes, I do believe everything is relevant, that's all.  Hardcore?  Probably.  But I'm okay if you have a different programming style.  We all do.
Title: Re: error msg?
Post by: jj2007 on July 15, 2012, 04:44:29 PM
Quote from: satpro on July 15, 2012, 09:09:52 AMI can literally see mouse activity in the task manager.

Hardcore assembler coders measure it, so give us figures: Is this CPU weak enough to turn an extra 0.00008 milliseconds per WM_MOUSEMOVE into "activity" in the task manager?

So go and test it with one of the standard Windows apps that you find in \masm32\examples, then we have something real to discuss.

Just in case your task manager doesn't notice your frenetic attempts: A WM_MOUSEMOVE per se needs 600 cycles, plus 3 for a little push'n and popp'n. But there are apps out there in the evil Microsoft & Adobe etc world which do, in the WM_MOUSEMOVE handler, incredibly slow things that may take ten-thousands of cycles... and that rubbish will indeed show as "activity" in the task manager".
Title: Re: error msg?
Post by: shankle on July 15, 2012, 08:57:01 PM
This is not about my main problem but am curious why this messagebox is causing problems.
This code causes the messagebox to go into a loop from which I have to
reboot the puter to get out of it. It never goes to WM_CREATE.
WndProc:
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebp,ebx,edi,esi
        Local hMemory,stm:SYSTEMTIME,ps:PAINTSTRUCT,hdc,hdcPrn
       
;   USED ONLY DURING TESTING PHASE
;TM8              db   'begin of wndproc',0
      pushad
      invoke MessageBox, NULL,addr TM8,NULL,MB_OK 
      popad   
;   test end

;.WM_CREATE
        cmp D[iMsg],WM_CREATE
         jne >>.WM_CHAR         
;.........................................       
This code does execute WM_CREATE and then goes back to my original problem
which I'm still trying to resolve.
WndProc:
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebp,ebx,edi,esi
        Local hMemory,stm:SYSTEMTIME,ps:PAINTSTRUCT,hdc,hdcPrn         

;.WM_CREATE
        cmp D[iMsg],WM_CREATE
         jne >>.WM_CHAR         
Title: Re: error msg?
Post by: jj2007 on July 15, 2012, 09:07:25 PM
Maybe GoAsm is different, but with Masm a uses ebp causes serious problems when local variables are present, because ebp gets automatically saved by the frame.
Title: Re: error msg?
Post by: shankle on July 15, 2012, 09:10:50 PM
OK JJ,
Took out the EBP and the same problem persists.
Thanks
Title: Re: error msg?
Post by: jj2007 on July 15, 2012, 09:55:14 PM
Post the exe, maybe with Olly I could tell you more.
Title: Re: error msg?
Post by: satpro on July 16, 2012, 04:22:19 AM
Quote from: shankle on July 15, 2012, 08:57:01 PM
This is not about my main problem but am curious why this messagebox is causing problems.
This code causes the messagebox to go into a loop from which I have to
reboot the puter to get out of it. It never goes to WM_CREATE.
WndProc:
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebp,ebx,edi,esi
        Local hMemory,stm:SYSTEMTIME,ps:PAINTSTRUCT,hdc,hdcPrn
       
;   USED ONLY DURING TESTING PHASE
DATA SECTION <--Try adding this
;TM8              db   'begin of wndproc',0
CODE SECTION <--and this
      pushad <-- why?
      invoke MessageBox, NULL,addr TM8,NULL,MB_OK 
      popad <-- why?   
;   test end

     


Are you putting the string in label TM8 right in-line with your code, or do you keep the semi-colon (comment) when you test and put the data elsewhere?  If the semi-colon is removed and that's your actual data, then put "DATA SECTION" right before and "CODE SECTION" right after the string line.  I would say the computer thinks the string is code and is trying to execute it.  It's right in the middle of a code section.  Also, jj is right--the EBP needs to come out.  Is that message box the first thing in your Window procedure?  If so, it's getting called a lot.


jj,
You can cut & paste that mouseover stuff and make snarky demands all day long.  That doesn't change the fact that you're unwilling to admit to pushing registers un-necessarily.  I'm done with the back and forth.  Insult someone else.
Title: Re: error msg?
Post by: dedndave on July 16, 2012, 05:51:35 AM
the MessageBox API preserved EBX, EBP, ESI, and EDI for you
you don't have anything in EAX, ECX, or EDX that needs to be preserved
WndProc:
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,stm:SYSTEMTIME,ps:PAINTSTRUCT,hdc,hdcPrn

      invoke MessageBox, NULL,addr TM8,NULL,MB_OK

;.WM_CREATE
        cmp D[iMsg],WM_CREATE
         jne >>.WM_CHAR

even if that does "work", it's going to generate a lot of message boxes - lol
when a window is created, it receives several messages
if you're not using Vista, you might be happier using Beep...
WndProc:
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,stm:SYSTEMTIME,ps:PAINTSTRUCT,hdc,hdcPrn

      invoke Beep,800,40

;.WM_CREATE
        cmp D[iMsg],WM_CREATE
         jne >>.WM_CHAR
Title: Re: error msg?
Post by: shankle on July 16, 2012, 06:49:42 AM
Hi JJ,
Here is the ".exe" of my attempt at GoAsm.  I have zipped it to
conform to Hutches regs.
It is NOT a working program. It will take you to the Wndproc 
and die right there.
Have fun. I sure am ;)
Title: Re: error msg?
Post by: shankle on July 16, 2012, 06:58:04 AM
Hi Satpro,
I sent you a message (I thought), Must have been in Sandboxie when I did it.
The TM statement is just there to remind  me what I coded.
It is defined in the Data Section.
I have remove  ebp.
I thought that the ";" was recognized in GoAsm as a comment. Am I wrong?

This messagebox is for testing ONLY. It will be removed as I get the program
working. Push/pop is there in the event i missed something which I obviously
have.
Title: Re: error msg?
Post by: shankle on July 16, 2012, 07:02:54 AM
HI Dave,
Using Window 7 pro.
It does generate a lot of messages. Don't understand why.
Taking out the push/pop doesn't really make it any better.
Purpose in using it was to find out were my code was taking me.
Title: Re: error msg?
Post by: satpro on July 16, 2012, 08:03:46 AM
Hi shankle,


Yes, the ";" is a comment.  Block comments are /* and */.  (no period)
I didn't know if you pulled the semi-colon to run the code.  I really do think you need to move that message box call.  Every time you get any kind of message that thing will run because it's first up in the WndProc.


I really hope you stick with GoAsm.  I like Masm, too, but just really enjoy coding with GoAsm.  Granted, there's a lot more code written for Masm and this is a Masm forum, but Jorgon really wrote a nice assembler and linker.  It's not laden with lots of extras, and is basically a 32/64-bit-only assembler, which is great.  It's simple, but powerful.  Kind of like the assembler I started with way back when.  And man, is it fast!  The thing I'm doing now is about 72k with about 30 files and it finishes in a couple of seconds.  I did have to read through the manual several times and usually keep it open while I program for things like syntax.  I use it with Notepad++ and can keep all the files right there with asm color-coding and unreal search/replace features.  It compiles & executes right from the editor.  The big difference between that and qeditor, which I like, too, is the tabbed files and multiple document (side by side) views.  What do you use?


Also, do you think there's any way I could look at the source (the startup, winmain, and data declaration) for your test program?  Maybe print it out and look at it closer.  The answer might just be "right there."  You never know.  I downloaded the .exe but didn't run it yet.  I've got a lot of stuff opened up right now 'cuz I'm coding.  But once we get your Window procedure ironed out you should be good to go.  That really is the hard part in the beginning.  Later, you'll laugh about it, I promise.
Title: Re: error msg?
Post by: shankle on July 16, 2012, 08:52:50 AM
Hi Satpro,
Right now I'm in Frown mode.
I kind of expected it to work right out of the box.
Yes, It's going to be some kind of embarrassing error.

I started back in the 60s with the Assembler from IBM.
I like it better than Masm or GoAsm. It had a length code for everything
which I kind of miss.
It always is.
Title: Re: error msg?
Post by: jj2007 on July 16, 2012, 08:57:23 AM
Quote from: shankle on July 16, 2012, 06:49:42 AM
Hi JJ,
Here is the ".exe" of my attempt at GoAsm.  I have zipped it to
conform to Hutches regs.
It is NOT a working program. It will take you to the Wndproc 
and die right there.
Have fun. I sure am ;)

Thanks. As it seems, the very first message quits with a "ret", not with calling DefWindowProc; and of course it returns to no man's land. So you better check why the WM_CREATE handler does not call DefWindowProc.

As a general remark, using a MsgBox at the entry of WndProc cannot work (I think satpro mentioned that already). You better use console assembly & link, and a pushad / print whatever / popad sequence.

HTH, jj
Title: Re: error msg?
Post by: shankle on July 16, 2012, 01:06:07 PM
Thank you JJ.
You made me take another look at WM_DESTROY.
When I converted this from MASM32 to GoAsm I got the
branch wrong.
Now the 1st window is flashing on the screen and goes to
"the program has stopped working".
To tired tonight. Will give it a rest and try tomorrow to
figure it out.
Title: Re: error msg?
Post by: wjr on July 16, 2012, 01:12:53 PM
The other correction would be at the end of each message that you do process to place a jmp instruction (otherwise you continue the message comparisons and eventually end up at DefWindowProc). So it should look like something this:

jmp >.Return0     ;<--- at the end of each message that you process, usually should return 0
.WM_DESTROY
cmp D[iMsg],WM_DESTROY
jne >.Default      ;<--- no more messages to check, so pass do DefWindowProc
.Return0
xor eax,eax        ;<--- message processed, usually return 0
.Return
ret
.Default
INVOKE DefWindowProc, [hWnd], [iMsg], [wParam], [lParam]
ret
Title: Re: error msg?
Post by: shankle on July 16, 2012, 10:52:11 PM
Getting there.
GoAsm complains about the 1st branch to Out2.
As you see it, it complains that the branch is to far.
If I change it to "jl >>.Out2" it gives an error message that
it is past the end of the program.       

       cmp D[holdR], 5
         jl >.Out2   ;** GoAsm complains about this branch**       
       add ebx, 4
       invoke WriteToPrinter, [hdcPrn],2926,3206,1837,ebx         
       cmp D[holdR],6
         jl >.Out2       
       add ebx, 4
       invoke WriteToPrinter, [hdcPrn],2926,3206,2035,ebx         
       cmp D[holdR],7
         jl >.Out2       
       add ebx, 4
       invoke WriteToPrinter, [hdcPrn],2926,3206,2233,ebx         
       cmp D[holdR],8
         jl >.Out2       
       add ebx, 4
       invoke WriteToPrinter, [hdcPrn],2926,3206,2430,ebx   
     
.Out2       








Title: Re: error msg?
Post by: wjr on July 17, 2012, 02:27:23 AM
I shall look into correcting the Line Number given for that GoAsm error.

I suspect that your code snippet is not within a FRAME...ENDF. In that case, your labels beginning with a period (.Out2) have a local scope extending between the unique code labels with a colon that surround it. In other words, the label for the jump in jl >>.Out2 is not found since between the jump instruction and the jump target you have at least one unique label "SomeLabel:" defined. Some solutions...

- The above does not take place within a FRAME...ENDF block; the scope of the label is local to FRAME...ENDF.
- Perhaps you can go more local with ".SomeLabel" instead of "SomeLabel:"
- Use an unscoped re-usable label made up of digits or a character+digit(s):

cmp D[holdR],5
jl >>L2
;
;
SomeLabel:
;
;
L2:
Title: Re: error msg?
Post by: shankle on July 17, 2012, 03:55:53 AM
Thanks WJR for replying.
I did not fully understand what you just wrote.
So let me explain my code more fully.
The code in the snippet above is within the Wndproc frame/endf code.
They should all be of a local scope I think. At least that's what I intended.
As you can see from the snippet there is nothing between the first Out2
and the label ".Out2" other than other Out2s.
Title: Re: error msg?
Post by: wjr on July 17, 2012, 12:55:04 PM
I do not get an error at my end with the required long jump, and unfortunately can not see why else an error would occur from what you have given.

If the L2 variation above does not work, then another way, since it looks like you are off by only 8 bytes, would be to avoid the long jump with shorter code... I do see some repetitive memory access that could be avoided with register usage if esi or edi were available and loaded with and then used instead of [holdR].
Title: Re: error msg?
Post by: dedndave on July 17, 2012, 08:58:01 PM
i don't know if GoAsm uses processor directives or not
but, if he has it set for .386, it might cause troubles
Title: Re: error msg?
Post by: shankle on July 17, 2012, 09:48:51 PM
Not using ".386".

The code relating to "Out2" is working now. Have no idea why
it didn't work in the 1st place. Moving on....

The following code is causing the program to fail. I get a clean
compile and link. It is caused by the "SetMapMode" API.
No matter if I do this "wm_text or [wm_text]" the instruction
causes the program to fail. This instruction works fine in MASM32:

;in data section
colortxt         dd       00ffffffh      ; white

; in code section
WndProc:
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,stm:SYSTEMTIME,ps:PAINTSTRUCT,hdc,hdcPrn

.WM_PAINT
        cmp D[iMsg],WM_PAINT
        jne >>.GetOut2     

         invoke BeginPaint, [hWnd],[ps]
         mov [hdc],eax

         invoke SetTextColor, [hdc],[colortxt]    ; text color white
         invoke SetBkMode, [hdc],TRANSPARENT
         invoke SetMapMode,[hdc],MM_TEXT
   ; (lots of code here)

.GetOut2
        cmp D[iMsg],WM_DESTROY 
         jne >.default 
         invoke PostQuitMessage,NULL
.return0                 
         xor eax,eax
         ret
.default
      invoke DefWindowProc, [hWnd],[iMsg],[wParam],[lParam]
   ret
    ENDF   




Title: Re: error msg?
Post by: wjr on July 18, 2012, 03:46:47 AM
Although I saw it to Begin with, another potential cause of failure would be the hdc value, and tracing that back to the source gives this correction:

invoke BeginPaint, [hWnd], ADDR ps
Title: Re: error msg?
Post by: shankle on July 18, 2012, 09:52:05 PM
Can't get this code to work in GoAsm.

; from the SystemTime structure
         xor ebx,ebx
         mov bx, [stm.wDay]               
; stm.day has the value of 14h

;Doesn't work         
         cmp D[ebx],0000000eh   
          jbe >>.Somewhere
          jmp >.ddd
; short jump
.ddd

;eeej defined in the data section                   
eeej     dd 0000000eh                   
;Doesn't work         
         cmp D[ebx],addr eeej   
          jbe >>.Somewhere
          jmp >.ddd                     
; short jump
.ddd


Title: Re: error msg?
Post by: satpro on July 19, 2012, 04:00:16 AM

; from the SystemTime structure

xor ebx,ebx
mov bx, [stm.wDay]          ; or: movzx ebx, W[stm.wDay] and eliminate the xor code
; stm.day has the value of 14h
;Doesn't work
cmp D[ebx],0000000eh    ;this is comparing the value at the address contained in ebx to 0eh ( try: cmp ebx, 0eh  [means cmp 14h to 0eh])
jbe >>.Somewhere         ;there is no address in ebx, only a value (14h)
jmp >.ddd
; short jump

.ddd

You have a System Time Value in bx.  The brackets around ebx are telling it to treat the value in ebx (the day) as a ptr to an address (00000014h), which doesn't exist in your process space (means compare value at address 00000014h to 0eh).  Does it crash?... If all you want to do is compare the value held in ebx to the number 0eh, then just remove the brackets (and the D--it's implied in this case).  The 'D" is like "DWORD PTR" in Masm, just shortened up a bit in GoAsm. try: cmp ebx, 0eh  (means cmp 14h to 0eh)


The instruction "movzx" will put a dword into ebx for you, padding the word from [stm.wDay] with zeroes.  Then you will no longer need to clear ebx first


;eeej defined in the data section

eeej     dd 0000000eh
;Doesn't work
cmp D[ebx],addr eeej
jbe >>.Somewhere
jmp >.ddd
; short jump

.ddd


[/size][size=78%]Would cmp ebx, [eeej] work for you?  (to compare what's in ebx to what's in eeej).  Again, in this case ebx IS a dword, so it only compares to dwords--no "D" needed here.[/size]
Title: Re: error msg?
Post by: shankle on July 19, 2012, 04:39:49 AM
Hi Satpro,
Will give your suggestions a try.
The "moczx" wants a "D" in the  movzx instruction..
Then you have to put [] around eax.
Obviously I'm having syntax problems.

To [] or not to [].
To addr or [].
Changes from "if" to "cmp" is causing major problems.
Coming along, I now get my 1st screen and then
the message "My Prog has stopped working".
What I need to do is go from the 1st screen to "WM_CHAR"
to input data.
Yes I read the manual but not with 100% understanding.
Time will cure all I suppose.....
Title: Re: error msg?
Post by: satpro on July 19, 2012, 11:50:33 AM
If the value in [stm.wDay] is a word then you code ->movzx ebx, W[stm.wDay].  It means you're moving a zero-extended WORD value into ebx.  It adds 16 zeroes to a word value.  If it was a byte you'd use a "B" and it would add 24 zeroes.  In GoAsm the use of brackets when addressing memory is mandatory.  Brackets around a register works the same.  No brackets around a register refers to what's in that register--not some address.  Let's say you do this:


DATA SECTION
GoAsm  dd  255


CODE SECTION
mov esi, ADDR GoAsm      ;get the address of the GoAsm variable into esi


Now, to access variable [GoAsm] using esi:


mov eax, [esi]                  ;this time no "D" because eax is 32-bits--that's known.  It expects a DWORD
                                      ;eax will now contain "0x000000FF"
But, if you do this:
movzx eax, W[esi]           ;you need the "W" because you're accessing something less than a full DWORD
inc B[esi]                         ;you need the "B" (or W or D) because you're incrementing what's in the address esi is pointing to


That inc affects flags, so it matters what size you're working with.  Pretending the value you are incrementing = 255 ($FF) a BYTE would roll over to 0, setting the Zero flag, but a WORD or DWORD won't.  A WORD would have to = 65535 ($FFFF) to inc and roll over to 0.  So you need to specify what size you're working with.  GoAsm doesn't type-check, so that 255 in variable [GoAsm] can be interpreted in different ways; that is, 1,2 or 4 bytes.  Memory works the same way:


inc W[GoAsm] will work on a WORD, the first 2 bytes only, even though [GoAsm] is declared as 32-bits.


Let's say:
GoAsm  dw  255 (WORD)


Provided it's not at the end of your declared data, you can still access a DWORD at variable [GoAsm]:
cmp D[GoAsm], 3



ADDR works with the address of some label.  It won't tell you what's in memory there.  That's what the brackets do.
Title: Re: error msg?
Post by: jj2007 on July 19, 2012, 03:35:07 PM
Quote from: satpro on July 19, 2012, 11:50:33 AMGoAsm doesn't type-check, ...

GoAsm  dw  255 (WORD)

So would a simple inc [GoAsm] throw an error, or would it be encoded using a default size, i.e. DWORD? Masm and JWasm would use WORD in this case.
Title: Re: error msg?
Post by: satpro on July 19, 2012, 07:30:45 PM
Hi jj,


It would give you a type expected (B,W, or D) error.
Title: Re: error msg?
Post by: shankle on July 19, 2012, 09:51:56 PM
Thanks Satpro.
It worked just fine.
Title: Re: error msg?
Post by: shankle on July 22, 2012, 02:29:48 AM
Got a lot of the bugs out of My Prog. It is now giving this message in WM_Create
using GetLastError code: "data area passed to a system call is to small".
The EnumPrinter has the cbBuf set to zero.
I tried to use "dwtoa" to find out what was in the pcbNeeded parameter
but it did not execute. I obviously have some [] or addr incorrect.
The DWTOA code is by WJR.

.data
dwNeeded   dd  0
dwReturned dd  0
TM18       db   'dwNeeded',0
convfld    db   '          ',0

.code
; other goodies

WndProc:
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hdc,hdcPrn
;.WM_CREATE
        cmp D[iMsg],WM_CREATE 
        jne >>.WM_CHAR         
        invoke  EnumPrintersA, PRINTER_ENUM_LOCAL,NULL,4,NULL,0,\
                [dwNeeded],[dwReturned]

;   test begin
;   edx is the input field
;   ebx  convfld  is the output field 
    pushad
    mov edx, [dwNeeded]
     mov ebx, addr convfld
     mov [BufAdd],ebx
     invoke    dwtoa, edx, [BufAdd]      ; Hex DD to string
     invoke MessageBox, NULL,[TM18],[convfld], MB_OK
     popad
;   test end
        jmp >>.default
; other goodies

;code per WJR
dwtoa:
     FRAME dwValue,lpBuffer
     USES esi,edi
   
    ; -------------------------------------------------------------
    ; convert DWORD to ascii string
    ; dwValue is value to be converted
    ; lpBuffer is the address of the receiving buffer
    ; EXAMPLE:
    ; invoke dwtoa,edx,addr buffer
    ;
    ; Uses: eax, ecx, edx.
    ; -------------------------------------------------------------
      mov   eax,[dwValue]
      mov edi,[lpBuffer]

      test eax, eax         ; is the value negative
      jns >
      mov B[edi], '-'         ; store a minus sign
      inc edi
      neg eax              ; and invert the value
:
      mov esi, edi           ; save pointer to first digit
      mov ecx, 10
.convert
      test eax,eax           ; while there is more to convert   
      jz >
      xor edx, edx
      div ecx              ; put next digit in edx
      add dl, '0'           ; convert to ASCII
      mov [edi],dl           ; store it
      inc edi
      jmp <.convert
:   
     mov B[edi], 0          ; terminate the string

.reverse                    ; We now have all the digits,
                            ; but in reverse order.
      cmp esi,edi
      jae >
      dec edi
      mov al,[esi]
      mov ah,[edi]
      mov [edi],al
      mov [esi],ah
      inc esi
      jmp <.reverse
:
    ret   
    endf








Title: Re: error msg?
Post by: dedndave on July 22, 2012, 03:00:23 AM
the idea is
1) call the function once to get the required buffer size by setting cbBuf to 0
2) allocate the buffer - size = cbNeeded
3) call the function again to fill the buffer - this time, pass a pointer to the buffer and it's size

it can be used with a pre-determined buffer the first time, of course
but - the code is probably simpler if you just get the size first
Title: Re: error msg?
Post by: wjr on July 22, 2012, 03:30:58 AM
You are correct in where you are obviously incorrect. For a 32-bit program, (most) arguments passed to a function are 32-bit, so generally if they are looking for a string or a more complicated structure, what you pass to the function is a pointer to that string or structure. In GoAsm syntax, that would require something like ADDR SymbolName, so one correction is here:

invoke MessageBox, NULL, ADDR TM18, ADDR convfld, MB_OK

If you use [SymbolName], that passes a 32-bit value. If you look at the API documentation for a function, those parameters that have an LP prefix are going to require a pointer with ADDR. In the case of EnumPrinters, you have correctly defined DWORDs to hold the values, but the function requires a pointer to these, so the next correction:

invoke  EnumPrintersA, PRINTER_ENUM_LOCAL,NULL,4,NULL,0,\
                ADDR dwNeeded, ADDR dwReturned
Title: Re: error msg?
Post by: dedndave on July 22, 2012, 03:52:07 AM
to add to what Wayne stated...

the "lp" prefix is usually used to refer to a "long pointer" - which is a 32-bit address
in the case of this function, they just used "p" for "pointer"
in a 32-bit program, "p" also refers to a 32-bit address
that can be a little confusing   :biggrin:

as an example, one of the EnumPrinters function parameters is named "pcbNeeded"
that means they want you to pass the address of a dword variable that might be named "cbNeeded"
while "cbNeeded" refers to a byte-count, it is a dword in size   :P

damned Hungarians   ;)
Title: Re: error msg?
Post by: shankle on July 22, 2012, 07:37:56 AM
Thanks all for the help.
The previous items in WM_CREATE seem to check out fine now.
However the program is still not printing.
I have included a snippet of the code that might be in error.
Of course it could be something else.

.data
PT2       db  '01020207010302040105020602030208',0             
            db  '01010103020501070208010402060106',0             
            db  '01040102010102060207010802010105',0                                         
saveebx   dd       0
holdR       db   "  ",0
             DOCINFOA <sizeof(DOCINFOA),AppName,NULL,NULL,0>
; other code

WndProc:
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hdcPrn
; other code
        invoke StartDoc, [hdcPrn],addr doci
       
         lea ebx,PT2
         mov [saveebx],ebx    ; address PT2 in saveebx
       
; other code
         mov ebx, [saveebx]   ; address in ebx
; not sure if ebx should have " []"  or not in invoke         
         invoke WriteToPrinter, [hdcPrn],393,660,1045,ebx         
               
; other code
WriteToPrinter FRAME hdcPrn,Horz1,Horz2,Vert4,LpBuffer
; Have no idea which of the following two instructions are correct
       mov ecx,addr LpBuffer        ; address in LpBuffer of PT2
       mov ecx,[LpBuffer]             ; address in LpBuffer of PT2       

;This line is causing the problem - address in ecx should move data to ax
;Have a messagebox here and the program boombs after it.       
       mov ax,W[ecx]
       cmp al,030h
        jne >
         mov al,020h
:
       mov W[holdR],ax                         
       invoke TextOutA, [hdcPrn],[Horz1],[Vert4],[holdR],2       
     ret
     ENDF
     
Title: Re: error msg?
Post by: jj2007 on July 22, 2012, 04:19:38 PM
Check
holdR       db   "  ",0
The upper byte of that "fake dword" used in TextOut gets supplied by DOCINFOA. Now if the lowest byte of DOCINFOA contains something different from zero, you are in trouble ;-)

Edit: Sorry, I just saw you are using only 2 bytes. Disregard this post, please.
Title: Re: error msg?
Post by: wjr on July 23, 2012, 04:34:15 AM
I believe what you had originally was correct and the problem was elsewhere. If your program doesn't work and you are coming from a working MASM program, then the error(s) are somewhere in your translation to GoAsm syntax, and you should really be stepping through your code in a debugger to quickly track these down. Another alternative is re-comparing to the MASM source code. The "not sure" and "have no idea" are a little worrisome. There is a big difference between [ebx] and ebx, and the syntax in this case is the same between the two assemblers (although in other cases some differences with GoAsm B/W/D/Q prefix vs MASM PTR variations). There is also a big difference between [LpBuffer] and ADDR LpBuffer (for the first one, GoAsm requires the [] where MASM allows LpBuffer... for the second one, if I recall correctly you would see MASM with OFFSET LpBuffer).
Title: Re: error msg?
Post by: dedndave on July 23, 2012, 05:47:58 AM
in masm, OFFSET is used for globals
ADDR can be used for either locals or globals - i prefer to use it only for locals
Title: Re: error msg?
Post by: satpro on July 24, 2012, 07:03:10 AM
In GoAsm both ADDR and OFFSET are accepted.


From the GoAsm manual:

"In order to get the offset in GoAsm you must use
MOV EBX,ADDR wParam
or if you prefer
MOV EBX,OFFSET wParam
which means the same thing"
Title: Re: error msg?
Post by: MichaelW on July 24, 2012, 07:22:14 AM
For MASM ADDR is valid only with INVOKE.
Title: Re: error msg?
Post by: shankle on July 25, 2012, 07:54:11 AM
Been over this before but I still am not able to print anything.
So I decide to start testing in WM_CREATE again.
MASM32 was using "winspool.inc" for the printer.
EnumPrintersA fails with a buffer to small error

.data
dwNeeded    dd  0
dwReturned  dd  0
pinf04           dd  0

.code
; other code

WndProc:
        FRAME hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,hdc,hdcPrn

;.WM_CREATE
        cmp D[iMsg],WM_CREATE 
        jne >>.WM_CHAR                 
                   
        invoke  EnumPrintersA, PRINTER_ENUM_LOCAL,NULL,4,NULL,0,\
                addr dwNeeded,addr dwReturned               
       invoke  GlobalAlloc, GHND,addr dwNeeded
       mov       [hMemory], eax
       invoke  GlobalLock, eax      
       mov       [pinf04],eax   
       mov       ebx,eax   
        invoke  EnumPrintersA, PRINTER_ENUM_LOCAL,NULL,4,[pinf04],\
                          addr dwNeeded,addr dwNeeded,addr dwReturned
        lea eax, [ebx+PRINTER_INFO_4.pPrinterName]                                          
        invoke  CreateDC, NULL,eax,NULL,NULL                              
       mov       [hdcPrn],eax
       mov       [hdc],eax
       invoke  GlobalUnlock, [hMemory]   
       invoke  GlobalFree, [hMemory]      
        jmp >>.default
; other code       
       endf
Title: Re: error msg?
Post by: Yuri on July 25, 2012, 12:13:45 PM

invoke  GlobalAlloc, GHND,addr dwNeeded

The second argument should be [dwNeeded].
Title: Re: error msg?
Post by: wjr on July 26, 2012, 08:39:02 AM
In the second call to EnumPrinters, the third last argument cbBuf should also be [dwNeeded].
Title: Re: error msg?
Post by: shankle on July 31, 2012, 01:40:07 AM
I'll try one more time and then I'll have to abandon Goasm.
I know I have been a pest - sorry.

MASM32 was using "winspool.inc" for the printer.
Enumprinter 2 never gets the name of the printer in parmeter 4 (PrintCString).
It shows executing clean.
Therefor CreatDC does not work.
I have been playing with this for days.
PrintDlgEX  won't work
I can get the Buffer length in dwNeeded which is 72.

.data
dwNeeded    dd  0
dwReturned  dd  0
PrintCString   db   90 DUP 0    ; buffer to receive the printer name

.code
; other code

WndProc:
        FRAME hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,hdc,hdcPrn

;.WM_CREATE
        cmp D[iMsg],WM_CREATE 
        jne >>.WM_CHAR                 
        invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,NULL,\
                0,addr dwNeeded,addr dwReturned
   invoke  GlobalAlloc, GHND,[dwNeeded]
   mov       [hMemory], eax
   invoke  GlobalLock, eax   
;       mov       ebx,eax
       invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,addr PrintCString,\
                                [dwNeeded],addr dwNeeded,addr dwReturned
;        lea edx, [ebx+PRINTER_INFO_4.pPrinterName]
        invoke  CreateDC, NULL,addr PrintCString,NULL,NULL
       mov       [hdcPrn],eax
       invoke  GlobalUnlock, [hMemory]   
       invoke  GlobalFree, [hMemory]   
       jmp >>.default
       endf
Title: Re: error msg?
Post by: wjr on July 31, 2012, 05:41:17 AM
Although there is a bit of a learning curve with GoAsm or any other assembler, there have been occasions here where the problem seems related more to the lower level understanding of pointers and their use in API functions.

Another correction in your earlier code, use mov instead of lea:
mov eax, [ebx+PRINTER_INFO_4.pPrinterName]

Your EnumPrinters returns an array of PRINTER_INFO_4 structures. CreateDC requires a pointer to a string for the name of the device (the first member of PRINTER_INFO_4), but with your recent "addr PrintCString" you are incorrectly passing the pointer to a PRINTER_INFO_4 structure. Note that there can be more than one of these structures, so perhaps you have more code that advances ebx to select which printer. There is also the GetDefaultPrinter API function.

I am in the process of getting printing operational for a program. I wasn't quite there yet, but unfortunately even with these corrections, the call to CreateDC fails. I have seen some sample code with the first argument as "WINSPOOL", but the documentation does recommend NULL for a printer. That sample code does pass a pointer to a DEVMODE structure though, perhaps that is the missing piece of the puzzle (although NULL does seem like it should work for a default initialization).
Title: Re: error msg?
Post by: jj2007 on July 31, 2012, 06:18:25 AM
TinyIDE has a printing routine. Look for PrintRTF inside the (Masm, not GoAsm) source, maybe you can get some inspiration. The *.asc file is the source of the source and opens in TinyIDE.exe.
Title: Re: error msg?
Post by: satpro on July 31, 2012, 07:43:36 AM

"I'll try one more time and then I'll have to abandon Goasm"
Well, is that fair?

In the first call to EnumPrinters the 4th param is NULL.  Doesn't that need to be a ptr to a buffer that receives an array of PRINTER_INFO_4 structures?  WinHlp doesn't mention anything about specifying a NULL ptr.  Then the 5th param should be a buffer size number, right?  Then, if more detailed info is needed, a 2nd call with a level 2 info structure can be called later.

Where are the comments (e.g. 1 per line of code?) that help you with what's going on?  Also, error-checking all OS calls would be a GREAT idea.  EnumPrinters returns TRUE if the function succeeds.  Same with GlobalAlloc (a ptr).  Where are the checks for success or failure?  You would know the call is not succeeding (and why) right then and there.  And then, why not use GMEM_FIXED | GMEM_ZEROINIT in GlobalAlloc and skip the Lock/Unlock calls, along with their lock counts?  The returned handle in this case is a ptr to your memory and you're freeing it almost immediately anyway, not that it matters.  It's your memory to use.

Wayne's advice about lea is right on the money.  You can refer to the values in a structure using the [register + structure.member] approach.  The assembler will handle the lea for you.

Maybe, and this is just a thought, how about try this in a console first, where you don't have the worries of the window proc heaped on top of a complicated series of calls to EnumPrinters?  It's really not that much code.  Move it back to the window when you iron everything out. 

It doesn't seem right that the assembler should have to take the fall here...
Title: Re: error msg?
Post by: shankle on July 31, 2012, 08:35:58 AM
Hi Satpro,
I've done all the error checking it's just not posted here. I also have comments and
their not posted here. Trying to keep it simple and straight forward.
It fails at CreateDC, Handle is not created. My understanding of the 1st EnumPrinter 
is that it is supposed to fail and only return the length of the buffer.
Title: Re: error msg?
Post by: satpro on July 31, 2012, 10:17:50 AM
Okay.  The call should be set up to succeed.  Make sure the buffer is large enough and that you use valid pointers.  The INFO_4 structure is 12 bytes per device.  Two ptrs and an attributes dword.  You said you needed 72 bytes, right?  90 should be fine, except it's not a multiple of 12.  Of course, the call still reports what you would need.  Or, use the larger buffer when you don't know the answer.  It's only a few bytes in DATA, right?

Also, "WINSPOOL",0 is used with computers after Win95/98.  And I just thought of something else.





Try this:

DATA SECTION
winspoolstring db "WINSPOOL", 0

CODE SECTION
mov ebx, ADDR PrintCString  (your buffer)
invoke CreateDC, addr winspoolstring, [ebx+PRINTER_INFO_4.pPrinterName], NULL, NULL


You can do this instead and GoAsm places the 0-term string 'WINSPOOL' in the CONST section for you (or DATA if no CONST or CODE if no DATA section):


CONST SECTION

CODE SECTION    (this might be easier for you)

mov ebx, ADDR PrintCString  (your buffer)
invoke CreateDC, 'WINSPOOL', [ebx+PRINTER_INFO_4.pPrinterName], NULL, NULL



Here's why:
The INFO_4 structure contains ptrs as it's first two members, and you want the first ptr.  Therefore, you would want the data at that address, which is the address of the string you need, contained within the structure, and not the address of the structure itself.  This means brackets and not ADDR.  Data, not address.

I have to admit that in using GoAsm you are working without a net most of the time because hardly anyone here uses it.  From my own experience I have found it to be a very efficient assembler that does ANYTHING I need it to do.  Not that Masm doesn't.  Once you get the hang of its (actually very simple) syntax there is nothing you cannot accomplish with it, and with no extra overhead.  But I don't use 'C' calls at all and macros almost never.  So for me GoAsm is ideal.  I'm not kidding--I had to read the manual a lot more than once and still refer to my printed copy frequently, although less and less.  But my source seems much easier to read with GoAsm; I like that very much.

In Masm you don't use ADDR much, maybe just with invoke.  The Masm guys already stated that.  If you feel more comfortable using OFFSET--use that instead.  Just remember that when accessing a variable's contents (its data) you use [somevariable] and in Masm you don't have to but can if you want --> somevariable or [somevariable].

Keep plugging away...
Bert
Title: Re: error msg?
Post by: MichaelW on July 31, 2012, 02:38:50 PM
Quote from: satpro on July 31, 2012, 10:17:50 AM
Okay.  The call should be set up to succeed.  Make sure the buffer is large enough and that you use valid pointers.  The INFO_4 structure is 12 bytes per device.  Two ptrs and an attributes dword.

The size would be 12 bytes in 64-bit code?
Title: Re: error msg?
Post by: satpro on July 31, 2012, 02:55:53 PM
Good catch, and no it wouldn't, but we were talking 32-bit code.
Title: Re: error msg?
Post by: shankle on July 31, 2012, 09:06:35 PM
Hi Satpro,
Thank you for replying.
Don't misunderstand me I am not blaming GoAsm for my inadequacies.
I have incorporated your suggestions and still no luck as you can see below.
I don't use macros either as I hate to dig all over the place to find out what
they need or mean. Same with includes. Only when necessary.

The next 3 lines are a quote from the Microsoft CreateDC API.
lpszDriver
"A pointer to a null-terminated character string that specifies either DISPLAY or the name
of a specific display device. For printing, we recommend that you pass NULL to lpszDriver
because GDI ignores lpszDriver for printer devices".

Enumprinter 2 puts garbage in parmeter 4 which is PrinterCString.
Therefor CreatDC does not work.

.data
dwNeeded         dd  0
dwReturned       dd  0
PrintCString       db   96 DUP 0    ; buffer to receive the printer name
winspoolstring   db   "WINSPOOL",0

.code
; other code

WndProc:
        FRAME hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,hdc,hdcPrn

;.WM_CREATE
        cmp D[iMsg],WM_CREATE 
        jne >>.WM_CHAR
        invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,NULL,\
                0,addr dwNeeded,addr dwReturned
       invoke  GlobalAlloc, GHND,[dwNeeded]
       mov       [hMemory], eax
       invoke  GlobalLock, eax   
        invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,addr PrintCString,\
                                [dwNeeded],addr dwNeeded,addr dwReturned                               
                                       
;   test begin
;tm2              db   'got to WM_CREATE',0
      pushad
      invoke MessageBox, NULL,addr TM2,addr PrintCString,MB_OK     
     popad     
;   test end
;The result of this test shows "yo@" with a tilder over the "o" in PrintCString.
;So good data is not getting into PrintCSring even though EnumPrinter is not
; failing. Of course this causes CreatDC to also fail.

        mov ebx,addr PrintCString
        invoke  CreateDC, addr winspoolstring,[ebx+PRINTER_INFO_4.pPrinterName],NULL,NULL
       mov       [hdcPrn],eax
       invoke  GlobalUnlock, [hMemory]   
       invoke  GlobalFree, [hMemory]   
                         
       endf
Title: Re: error msg?
Post by: satpro on August 01, 2012, 12:06:04 AM
Shankle,

I've read that about WINSPOOL, too.  The book I use for reference is the Windows 2000 API SuperBible and it makes a distinction between Win95/98 and 2000, which is more like today's OS.  It talks about WINSPOOL.  Maybe I'm mis-reading something there.

But I'll look into it today.


P.S.  Did you try the suggestion about using the ptrs on the first call to EnumPrinters?  Oh--if you're getting info on 6 devices (72 bytes) the first array in PrintCString might not be what you're looking for--just a guess.  The rest would offset by 12.  You are compiling Win32 and for Ansi chars, right?
Title: Re: error msg?
Post by: satpro on August 01, 2012, 01:06:53 AM
Shankle,
After writing the last post to you I got to thinking.  You know, I feel like I'm just throwing guesses out there without knowing what I should know to actually help.  At the very least it's unfair to you.  At it's worst I look stupid for throwing out guesses.  There is just this small bit of visible code to go on that tells very little about the actual program.

How about this?  Zip up your GoAsm folder and email it to me.  I promise no judgments on coding style or any of that.  I have this console "debugger" I wrote that tells me variables, flags, etc.  I use it a lot for tricky new stuff.  On top of that I bought the paid version of GoBug so I really will find the cause of this trouble.  But doing it this way now is getting all of us nowhere fast.

My idea is to isolate the Enum stuff and throw it into the console, and actually work with your code.  It probably won't take forever to find the answer.

You don't have to do that, but I think any more guessing is just "poking and hoping."

Bert
Title: Re: error msg?
Post by: shankle on August 01, 2012, 02:18:54 AM
Hi Satpro,
I have only 1 printer(HP Officejet Pro l7580).
Yes it is ANSI.
I don't mind the suggestions and I do try to test them.
I understand the problem of trying to help someone with your hands tied.
However IMHO the other parts of the program have nothing to do with
the EnumPrinters, CreateDC, GetDefaultPrinter, PrintDlgEX. All of which don't
work for me.

Title: Re: error msg?
Post by: wjr on August 01, 2012, 03:20:31 AM
As mentioned, with the corrections, your second call to EnumPrinters works just fine. Your PrintCString buffer gets filled with PRINTER_INFO_4 structures. To see this, correct your test as follows:

invoke MessageBox, NULL,addr TM2,[PrintCString],MB_OK
invoke MessageBox, NULL,addr TM2,[PrintCString+12],MB_OK
invoke MessageBox, NULL,addr TM2,[PrintCString+24],MB_OK
invoke MessageBox, NULL,addr TM2,[PrintCString+36],MB_OK
invoke MessageBox, NULL,addr TM2,[PrintCString+48],MB_OK
invoke MessageBox, NULL,addr TM2,[PrintCString+60],MB_OK


It seems like your call to CreateDC may require a pointer to a DEVMODE structure as the last argument (perhaps the 64-bit drivers are more picky if this was previously working on 32-bit).

I went a slightly different route with:
GetDefaultPrinter
OpenPrinter
DocumentProperties ;to get size of buffer for DEVMODE
GetProcessHeap
HeapAlloc
DocumentProperties
CreateDC

I did get this to work up to this point. However, for some reason ONLY while debugging, the first call to DocumentProperties fails. Searching the web, there does appear to be some difficulties with this function, as well as PrintDlgEx, on more recent 64-bit OS's.
Title: Re: error msg?
Post by: shankle on August 01, 2012, 03:29:24 AM
Thank you WJR,
I'm still working on the 32-bit version.
Haven't started to worry about the 64-bit code.
The 2nd EnumPrinter is now working correctly.
I can see my printer in the test messagebox.
So now the problem has moved to the "CREATEDC" api.
Title: Re: error msg?
Post by: shankle on August 06, 2012, 06:58:23 AM
More fun.
The 1st window is written to the screen for me to enter data for the program.
Then this wonderful Windows message appears: "program has stopped working".
I never get a chance to enter the data that's needed. Yes, I have probably screwed
up GoAsm or Windows or both somehow. Therefor wParam never gets loaded
with the keyed input before the Error message appears.
Title: Re: error msg?
Post by: Yuri on August 06, 2012, 11:26:11 AM
I suggest you run your program in a debugger. E.g. the freeware OllyDbg. This way you will see the offending command.
Title: Re: error msg?
Post by: shankle on August 13, 2012, 02:30:02 AM
I have shown below what happens in GoBUG at  the end of WM_PAINT after the
1st screen  is created. It shows the screen and then a Windows message is
presented " the program has ceased to function".  ".doneh" is at the very end
of WM_PAINT. If I insert a message box right after ".doneh", it lets me enter
my data and fails again for other reasons. This is my 1st attempt with Go Bug.
;------------------------------------------------------------------------
                 GoBug - copyright Jeremy Gordon 1996-2009
                Date: Sunday, August 12, 2012 Time: 11:51:18 AM
                                Dump of codepane

    ~~~WndProc.doneh:~~~>
    4045E4: PUSH EBP
    4045E5: ADD D[ESP],-54
    4045E9: PUSH [EBP+14]
    4045EC: CALL EndPaint(USER32.dll)
    4045F1: MOV ESP,EBP
    4045F3: POP ESI
    4045F4: POP EDI
    4045F5: POP EBX
    4045F6: POP EBP
    4045F7: RET 10   
    ~~~WndProc.WM_DESTROY:~~~>
    4045FA: CMP D[EBP+18],2
    4045FE: JNZ >404608
    404600: PUSH [EBP+20]
    404603: CALL PostQuitMessage(USER32.dll)   
    ~~~WndProc.default:~~~>
    404608: PUSH [EBP+20]
    40460B: PUSH [EBP+1C]
    40460E: PUSH [EBP+18]
    404611: PUSH [EBP+14]
    404614: CALL DefWindowProcA(USER32.dll)
    404619: MOV ESP,EBP
    40461B: POP ESI
    40461C: POP EDI
    40461D: POP EBX
    40461E: POP EBP
    40461F: RET 10
   
Title: Re: error msg?
Post by: dedndave on August 13, 2012, 04:37:03 AM
    4045E4: PUSH EBP
    4045E5: ADD D[ESP],-54
    4045E9: PUSH [EBP+14]
    4045EC: CALL EndPaint(USER32.dll)
    4045F1: MOV ESP,EBP
    4045F3: POP ESI
    4045F4: POP EDI
    4045F5: POP EBX
    4045F6: POP EBP
    4045F7: RET 10


there must be more to it than that   :P
the stack frame looks a little strange, there
we don't see the call to BeginPaint, nor the initialization of the stack frame
or - maybe that's it - lol
the sub 54h sounds like it might be making space for a PAINTSTRUCT

Jack...
i have repeatedly mentioned that you might post the full source
we have a hard time doing much in bits and pieces
it's like putting together a jigsaw puzzle with only 10% of the pieces