The MASM Forum

Projects => Rarely Used Projects => GoAsm => Topic started by: shankle on September 14, 2012, 10:32:05 PM

Title: 64 bit errors
Post by: shankle on September 14, 2012, 10:32:05 PM
Got my 1st 32-bit GoAsm program working.
Made a copy of it and named it  blah64.asm.
Ran it through AdaptAsm. The result showed about 300 changes
made by AdaptAsm.
When running it through the 64-bit batch file the following errors
occurred:
   ExitProcess, rax
   push rdx
   push rbx
   pop rbx
   pop rdx
   invoke GlobalLock, rax
   mov rbx,addr PrintCString
   invoke CreateDC, null,rdx,null,null
   lea rbx,PT2 (Gave invalid operand for this mnemonic)
   (and probably 500 more such errors)

To solve the GoAsm errors I put [] around the register causing the problem.
Two questions:
  1: thought AdaptAsm caught this type of error.
  2: is the error correction I made correct?
Title: Re: 64 bit errors
Post by: wjr on September 15, 2012, 03:36:49 AM
For point 2, no, you have made an incorrection... the code should still look similar; changing these registers to 64-bit should not involve a change to accessing memory with [register].

For point 1, those are not errors. However, AdaptAsm does not catch everything, so you should still go through line by line to see if any other changes need to be made. Although it gets a bit more complicated if you use floating-point or structured exception handling, you can still have one source file that assembles for either a 32-bit (with GoAsm /x86 command line option) or 64-bit (with GoAsm /x64 command line option) application.

You didn't specify which error you were getting. Given that there were so many, that they involve 64-bit registers, and you went with trying [ ], please check to make sure that you were building with one of the two above GoAsm command line options. Without these, GoAsm assumes 32-bit and sees rax as a symbol which you have not defined yet (which would require either [ ] or ADDR).
Title: Re: 64 bit errors
Post by: shankle on September 15, 2012, 06:32:54 AM
         9-14-2012

Thank you WJR for responding.
Please disregard my 1st fumblings.
I forgot the /x64 parameter in the GoAsm JCL.
I got the following error running GoAsm /x64.
Haven't had time to dig on the nitty-gritty of the sizes of the
registers in the Docinfo Struct. They are possibly wrong.
This was the 1st error I got when running GoAsm /x64.
Haven't gone any further as of this messgage.
             
hdcPrn           dd       0
                             
WndProc:
        FRAME hWnd,uMsg,wParam,lParam
        USES ebx,edi,esi
        Local DI:DOCINFO   
       
       mov eax, SIZEOF DOCINFO           ; fill in fields of the DOCINFO Struct
       mov [DI.cbSize],eax
       mov rax,addr AppName
       mov [DI.lpszDocName], eax
       mov D[DI.lpszOutput],NULL
       mov D[DI.lpszDatatype],NULL
       mov D[DI.fwType],0 

; other code             
       invoke StartDoc, [hdcPrn],addr DI       
       GoAsm 64 gives this error for the above instruction:       
         Only 32-bit or 64-bit register allowed as index register
                 
; other code             
       ENDF                           
             
       

                       
Title: Re: 64 bit errors
Post by: qWord on September 15, 2012, 06:55:14 AM
DI is a 16 Bit register -> rename your locale variable.
Title: Re: 64 bit errors
Post by: wjr on September 15, 2012, 11:04:38 AM
As an example of some the changes you will still need to look out for to avoid runtime errors, the DOCINFO structure has 3 pointers which switch size to 64-bits, so you should also make the following changes:


mov [DocI.lpszDocName], rax
mov P[DocI.lpszOutput],NULL
mov P[DocI.lpszDatatype],NULL


Although this was mentioned as an enhancement in the announcement for GoAsm 0.57.0.0 on the old forum, I see that the help file has not been updated for the P type indicator which can be used for switching between D/Q pointers (S was intended for B/W ANSI/Unicode string switching).

You would need to add this near the start of your source file


#if x64
#define P 8
#else
#define P 4
#endif


or even better just modify your windef.h header file with the above definitions after those for PTR on lines 271 and 283.
Title: Re: 64 bit errors
Post by: shankle on September 26, 2012, 09:07:35 PM
The DOCINFO struct is still giving me problems.

    9-26-2012
Tried 3 different lpszDocNames. All gave a GoBug error     
   
WndProc:
        FRAME hWnd,uMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,stm:SYSTEMTIME,ps:PAINTSTRUCT,hdc,doci:DOCINFO   
       
; other code                       
          #if x64
           #define P 8
          #else
           #define P 4
          #endif 

; other code               
       mov [rax],addr AppName
       
;GoBug gave error   
       mov P[doci.lpszDocName], rax
; or       
;GoBug gave error   
       mov P doci.lpszDocName, [rax]
; or       
;GoBug gave error   
       mov P[doci.lpszDocName], [rax]

; other code               
    ENDF             ; end of WndProc
-----------------------------------------

; This is part of ATODW in MASM32
;How do I change it for 64-bit?       
      lea rcx,[rcx+rcx*4]   ; ecx = ecx * 5
      lea rcx,[rax+rcx*2]   ; ecx = eax + old ecx * 10

      lea rax,[rcx+rdx]   ; move to eax and negate
--------------------------------

;  overwritten register see below
BufAdd  dd  0
hpn      db '   ',0
spn      db 0
   
;   edx is the input field
;   ebx  hpn is the output field   
       push [rbx]
;       lea rbx,[hpn]
       mov [rbx],addr hpn 
       inc ebx                       ; save 1st byte for # sign
       xor edx,edx
       movsx edx, B[spn]             ; input
       mov [BufAdd],ebx
       
; GoBug complains that rdx is overwritten by the 2nd parameter material     
; said to use another register
; DWTOA is a MASM32 routine
       invoke dwtoa, rdx,[BufAdd]     ; Hex DD to string
                                      ; output is in hpn                                   
       cmp B[hpn+2],030h
        jge >
         mov B[hpn+2],020h
:       
       mov B[hpn],023h      ; #
       inc B[spn]         
       pop [rbx]
       ret   
   
   
       
Title: Re: 64 bit errors
Post by: wjr on September 27, 2012, 06:41:25 AM
For the first one, you should be able to go with:

mov   [doci.lpszDocName],ADDR AppName

It looks like you or AdaptAsm did OK for that portion of the ATODW 64-bit conversion.

For the 64-bit calling convention, INVOKE passes the first 4 arguments in registers RCX, RDX, R8, and R9. The arguments are processed from right to left, so [BufAdd] would get placed into RDX overwriting whatever was there before the intended value of RDX would get placed into RCX. GoAsm gives this error with the suggestion to use another register (RCX would be more efficient if available).
Title: Re: 64 bit errors
Post by: shankle on September 27, 2012, 11:00:01 AM
Thanks WJR for helping
Gobug is complaining about 2 things. I have included the
routines that are causing the problems.

; atodw is a routine used in MASM32
; GoBug gives errors in the "lea" instructions
atodw:
       FRAME String
       USES edi,esi

      ;----------------------------------------
      ; Convert decimal string into dword value
      ; return value in eax
      ;----------------------------------------

      xor eax,eax
      mov esi,[String]
      xor ecx,ecx
      xor edx,edx
      mov al,[rsi]
      inc esi
      cmp al,'-'
       jne >   
      mov edx,-1
      mov al,[rsi]
      inc esi
:     

.doagain
     cmp al,0
       je >
      sub al,'0'   ; convert to bcd
; GoBug gives invalid operand     
      lea rcx,[rcx+rcx*4]   ; ecx = ecx * 5
; GoBug gives invalid operand     
      lea rcx,[rax+rcx*2]   ; ecx = eax + old ecx * 10

      mov al,[rsi]
      inc esi
      jmp .doagain
:
; GoBug gives invalid operand     
      lea rax,[rcx+rdx]   ; move to eax and negate

      xor eax,edx
      ret
      ENDF
     
----------------------------------------------------------
;Dwtoa is a MASM32 routine
;The invoke uses edx(RDX) so I don't see how I could change that to rcx
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[rdi], '-'         ; 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 [rdi],dl           ; store it
      inc edi
      jmp <.convert
:   
     mov B[rdi], 0          ; terminate the string

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

------------------------------------------
BufAdd  dd  0
hpn     db '   ',0
spn     db 0
   
;   edx is the input field
;   ebx  hpn is the output field   
       push [rbx]
;       lea rbx,[hpn]
       mov [rbx],addr hpn 
       inc ebx                       ; save 1st byte for # sign
       xor edx,edx
       movsx edx, B[spn]             ; input
       mov [BufAdd],ebx
       
; DWTOA is a MASM32 routine
; you suggested I change rdx to rcx
; don't see how this would agree with the Dwtoa invoke statement
       invoke dwtoa, rdx,[BufAdd]     ; Hex DD to string
                                      ; output is in hpn                                   
       cmp B[hpn+2],030h
        jge >
         mov B[hpn+2],020h
:       
       mov B[hpn],023h      ; #
       inc B[spn]         
       pop [rbx]
       ret
Title: Re: 64 bit errors
Post by: wjr on September 27, 2012, 01:03:48 PM
I think you mean GoAsm gives an invalid operand (GoBug is currently only 32-bit). Separate file? Please make sure you are building with /x64 on the command line (or /x86 for 32-bit).

The first argument to dwtoa is the value to be converted, such as a value (ex. 12345678h) or any register with a value (you were attempting rdx). The suggestion of using rcx would also involve changing your two lines above invoke using edx to this:
movsx   rcx,B[spn]             ; input
Title: Re: 64 bit errors
Post by: shankle on September 28, 2012, 06:56:35 AM
   9-28-2012
Thanks again WJR
I have included my jcl for running this program

Set INCLUDE=k:\codejps
Set PATH=k:\codejps
GoAsm /x64/b/c blah64.asm
GoLink /unused blah64.obj

Set INCLUDE=k:\codejps
Set PATH=k:\codejps
;!!! invalid
;GoAsm /b/c blah64.asm
GoAsm /x64/b/c blah64.asm
GoLink /unused /debug COFF blah64.obj

Got through the GoBub with no errors :biggrin:

----------------------------------------------
Am I right in this assumption?
for EX:       RAX
upper 8 bits no subset
subset       eax of RAX
subset        ax  of RAX
subset        ah or al of RAX

----------------------------------------------------
Using a messagebox I can get to UpDateWindow without any errors.
I guess the problem is with the way I have defined WndClassEX.

hBrush                dq       0
hInstance            dq       0
colorbk               dd       00ff0000h      ; blue
szDisplayName    db      'wc',0

WinMain:
    FRAME hInst,hPrevInst,CmdLine,CmdShow       
   LOCAL wc:WNDCLASSEXA,msg:MSG,hdc,rc:RECT,hWnd
   
   mov   Q[wc.cbSize], SIZEOF WNDCLASSEXA
      mov   Q[wc.style], CS_BYTEALIGNWINDOW       
   mov   Q[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   Q[wc.hIcon], rax
              invoke LoadCursor, NULL,IDC_ARROW   
              mov   Q[wc.hCursor], rax
   invoke CreateSolidBrush, [colorbk]          ; background color
              mov   Q[hBrush], rax
   mov   Q[wc.hbrBackground], rax
   mov   Q[wc.lpszMenuName], NULL
   mov   Q[wc.lpszClassName], OFFSET szDisplayName
   mov   Q[wc.hIconSm], 0
       
-------------------------------------------------
how can I preserve the registers when using the messagebox
to test the program? Pushad/popad doesn't work in 64-bit code

-----------------------------------------------------
How can I get a list of what my program looks like
when converted to 64-bit Assembler??? The /l gives
something different.
Title: Re: 64 bit errors
Post by: wjr on September 29, 2012, 06:53:22 AM
Correct in the assumption, extended to no subset for the upper 32 bits.

Wrong mov size for first two members, fix with D[wc.cbSize] and D[wc.style].

To save 'all' registers, you will need to do your own series of pushes and later pops (or create a macro and use that if you do this often).

Sorry, I am not sure what you are looking for in a "list of what my program looks like" if not the /l option.
Title: Re: 64 bit errors
Post by: shankle on September 29, 2012, 07:45:54 AM
Program still won't write to the screen with the changes you suggested.
Do I need to make a struct of Wndclassex? I think I need to add 4 bytes
after style and the only way I know how to do that is with a struct. I have
been unable to find a 64-bit struct for WndClassEx in the headers.

As to the listing. I would like to see the changes that AdaptAsm made to my
program. I'm looking at the code I wrote for the 32-bit program.
Thanks
Title: Re: 64 bit errors
Post by: wjr on September 29, 2012, 09:07:23 AM
Make sure you have the following before your #include lines:
#define WIN64
and this will switch to 64-bits where needed in the header files (ex. PTR becomes DQ), with GoAsm handling padding when needed.

For text file comparisons I can highly recommend ExamDiff Pro (I also need this for directory and binary file comparisons), but I see prestoSoft also has a freeware version ExamDiff, so definitely try that out.
Title: Re: 64 bit errors
Post by: shankle on September 30, 2012, 05:31:25 AM
         9-29-2012
; This code is from the working 32-bit program and outputs the
; first screen just fine       
#define LINKFILES
#INCLUDE windows.h
#define codejps

colorbk              dd       00ff0000h      ; blue
hBrush               dd       0
hInstance           dd       0
holdleft              dd       0
holdright            dd       0
holdbottom         dd       0
holdtop               dd       0       
savemiddleofX     dd       0
szDisplayName    db   'wc',0

WinMain:
    FRAME hInst,hPrevInst,CmdLine,CmdShow
   LOCAL wc:WNDCLASSEXA,msg:MSG,hdc,rc:RECT,hWnd
   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               ;  this code sets up cxclient/cyclient
     push ebx
     xor edx,edx     
     mov eax,[holdright]     ; find middle of line
     mov ebx,2               
     div ebx
     mov [savemiddleofX],eax   ; middle of screen
     pop ebx
     pop edx     
    INVOKE CreateWindow, addr szDisplayName,addr AppName,\              WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX,\
            [rc.left],[rc.top],[rc.right],[rc.bottom],NULL,NULL,[hInstance],NULL                   
         mov   [hWnd],eax                 
           
   invoke ShowWindow, [hWnd],SW_SHOWNORMAL
   invoke UpdateWindow, [hWnd]      

----------------------------------------------
This code is in the 64-bit version and does
not output the 1st screen
Got a clean compile, link and Gobug shows no errors
The messagebox at the end executes and when I click on OK
the program closes

#define LINKFILES
#define codejps
#define WIN64
#INCLUDE windows.h
   
colorbk              dq       00ff0000h      ; blue
hBrush              dq       0
hInstance          dq       0
holdleft              dq       0
holdright            dq       0
holdbottom         dq       0
holdtop              dq       0       
savemiddleofX    dq       0
szDisplayName   db   'wc',0
   
WinMain:
    FRAME hInst,hPrevInst,CmdLine,CmdShow       
   LOCAL wc:WNDCLASSEXA,msg:MSG,hdc,rc:RECT,hWnd

   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 rax,[rc.left]
     mov [holdleft], rax
     mov rax,[rc.right]
     mov [holdright],rax
     mov rax,[rc.bottom]
     mov [holdbottom],rax
     mov rax,[rc.top]
     mov [holdtop],rax     
     push rdx              ;  this code sets up cxclient/cyclient
     push rbx
     xor rdx,rdx     
     mov rax,[holdright]     ; find middle of line
     mov rbx,2
     div rbx                     
     mov [savemiddleofX],rax   ; middle of screen
     pop rbx
     pop rdx             

    INVOKE CreateWindow, addr szDisplayName,addr AppName,\            WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX,\
     [rc.left],[rc.top],[rc.right],[rc.bottom],NULL,NULL,[hInstance],NULL                   
         mov   [hWnd],rax                 
           
   invoke ShowWindow, [hWnd],SW_SHOWNORMAL
   invoke UpdateWindow, [hWnd]         
   
; temp code begin   
;tmsg2            db 'got to winmain',0
        invoke MessageBox, [hWnd], addr tmsg1, addr tmsg1, MB_OK ;true
; temp code end       
Title: Re: 64 bit errors
Post by: wjr on September 30, 2012, 09:13:15 AM
Except as noted in reply #10, your #9 code was fine with the Q[...].

A RECT structure does not have members that are pointers so they remain 32-bit. So most of that section will need to be changed back (not the push/pop rbx though... don't really need to save rdx here...  you can avoid use of rbx too, since dividing by two can be done with shr eax,1).
Title: Re: 64 bit errors
Post by: shankle on October 02, 2012, 07:32:01 AM
Made the changes you last suggested and the 1st screen still doesn't show.
The messagebox right after the "UpdateWindow" did NOT show.
The messagebox in WM_Create did show. Checking to see why the 1st
messagebox was bypassed. Think it is a sequence of events in windows
problem.

If GoBug doesn't debug 64-bit programs then I never need to run 64-bit
jcl for 64-bit programs. I did this not realizing GoBug was only a 32-bit
debugger.
Title: Re: 64 bit errors
Post by: japheth on October 02, 2012, 06:24:48 PM
Quote from: shankle on October 02, 2012, 07:32:01 AM
Checking to see why the 1st
messagebox was bypassed. Think it is a sequence of events in windows
problem.

Yes. WM_CREATE is send from inside CreateWindow(), so this is "the 1st".

Quote
If GoBug doesn't debug 64-bit programs then I never need to run 64-bit
jcl for 64-bit programs. I did this not realizing GoBug was only a 32-bit
debugger.

There are 64-bit debuggers: FDBG (written in FASM, has a GUI - it's advertised as AMD64 debugger, so I'm not 100% sure if it also works for Intel cpus), MS debuggers ( CDB, WinDbg ). Even if the debugger's user interface may be somewhat archaic - you can always code a hard breakpoint ( "int 3") in the assembly source, the debugger will stop and you can examine registers, see contents of variables, single-step, ....


   mov   D[wc.lpfnWndProc], OFFSET WndProc


You probably already changed the "D" to a "Q" ( pointers in Win64 are 64-bit ). That's better, but not perfect. It works as long as the address where the image is loaded is within the first 4 GB. The assembler cannot tell if this will be the case - the image base address is usually set by the linker. To make your code running in ALL cases, change it to:


   mov rax, OFFSET WndProc
   mov Q[wc.lpfnWndProc], rax


The reason for this weird necessity is a AMD64 peculiarity - it has only very limited support for 64-bit constants.


   invoke LoadIcon, NULL,IDI_APPLICATION
   mov   D[wc.hIcon], eax


All handles ( usually struct members beginning with a 'h' ) have been changed to 64-bit in Win64, so you'll have to change the second line to:


   mov   Q[wc.hIcon], rax

Title: Re: 64 bit errors
Post by: shankle on October 02, 2012, 10:34:43 PM
Thank you Japheth for your suggestions.
Will check them all out.
I saw your post on Jwasm in Ubuntu and didn't
think that Windows APIs would work in Linux.
Very interesting, most over my head, but maybe
when I have time, try to convert one of my programs
so that it will run on some Linux distro.

Title: Re: 64 bit errors
Post by: shankle on October 04, 2012, 12:15:59 AM
32-bit program is working.
64-bit program is not working.

WM_Create goes to the end of WM_Create then
Winmain executes to the UpdateWindow and the
screen appears.
WM_PAINT never executes.
Putting CS_HREDRAW/CS_VREDRAW in style has no effect.
Have a messagebox at the beginning of WM_PAINT and
it doesn't execute so I know it's not getting there.
Thanks for any suggestions.
Title: Re: 64 bit errors
Post by: qWord on October 04, 2012, 02:25:03 AM
you maybe show us you current code?
Title: Re: 64 bit errors
Post by: shankle on October 04, 2012, 06:48:10 AM
Thanks for responding qWord
Below is the code you requested.

        10-4-2012
#define LINKFILES
#define codejps
#define WIN64
#INCLUDE windows.h

DATA SECTION
BufAdd             dd       0
colorbk             dq       00ff0000h      ; blue
dwNeeded        dq       0
dwReturned      dq       0
hBrush             dq       0
hdcPrn             dq       0
hInstance        dq       0
holdleft           dd       0
holdright         dd       0
holdbottom     dd       0
holdtop           dd       0       
pinfo4            dq       0
savemiddleofX    dd       0

AppName            db   "blah1",0
datestring           db   "MM'-'dd'-'yyyy",0
szDisplayName    db   'wc',0
CommandLine LPSTR     ?

.code
start:
   invoke GetModuleHandleA, NULL
   mov    [hInstance],eax
   invoke GetCommandLine
   invoke WinMain, [hInstance],NULL,[CommandLine],SW_SHOWDEFAULT
;   invoke ExitProcess,rax  - GoAsm wants []
   invoke ExitProcess,[rax]
                   
WinMain:
    FRAME hInst,hPrevInst,CmdLine,CmdShow       
   LOCAL wc:WNDCLASSEXA,msg:MSG,hdc,rc:RECT,hWnd

   mov   D[wc.cbSize], SIZEOF WNDCLASSEXA
   mov   D[wc.style], CS_BYTEALIGNWINDOW
   mov   rax,offset WndProc   
   mov   Q[wc.lpfnWndProc],rax
   mov   D[wc.cbClsExtra], NULL
   mov   D[wc.cbWndExtra], NULL
   push  [hInst]
   pop   [wc.hInstance]
   invoke LoadIcon, NULL,IDI_APPLICATION
   mov   Q[wc.hIcon], rax
              invoke LoadCursor, NULL,IDC_ARROW   
              mov   Q[wc.hCursor], rax
   invoke CreateSolidBrush, [colorbk]          ; background color
              mov   Q[hBrush], rax
   mov   Q[wc.hbrBackground], rax
   mov   Q[wc.lpszMenuName], NULL
   mov   Q[wc.lpszClassName], OFFSET szDisplayName
   mov   Q[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
                 
; This code executed when turned on
; temp code begin   
;tmsg1            db 'got to end of winmain_cr',0
;        invoke MessageBox, [hWnd], addr tmsg1, addr tmsg1, MB_OK ;true
; temp code end       

   INVOKE CreateWindow, addr szDisplayName,addr AppName,\
         WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX,\
        [rc.left],[rc.top],[rc.right],[rc.bottom],NULL,NULL,[hInstance],NULL                   
;        mov   [hWnd],eax                                 
         mov   [hWnd],rax                                 

   invoke ShowWindow, [hWnd],SW_SHOWNORMAL
   invoke UpdateWindow, [hWnd]
; The above instruction executed and the screen appeared
; Then chaos.................            

; ===============================================================
;  Loop until PostQuitMessage is sent
; ===============================================================
L1:
INVOKE GetMessageA,addr msg,0,0,0
OR RAX,RAX              ;see if it is WM_QUIT
JZ >L2                  ;yes
INVOKE TranslateMessage,addr msg
INVOKE DispatchMessageA,addr msg
JMP L1                  ;after message dealt with, loop back for next one
L2:                     ;message was WM_QUIT
INVOKE UnregisterClassA   ;ensure class is removed
INVOKE ExitProcess,[msg.wParam]    ;wParam=exit code
ret

;      .StartLoop
;         INVOKE GetMessageA, addr msg,0,0,0
;;;          cmp eax,-1
;         or rax,rax   ; see if it is wm_quit
;          je >.ExitLoop
;          INVOKE TranslateMessage, addr msg
;          INVOKE DispatchMessageA, addr msg
;          jmp .StartLoop
;       .ExitLoop
;;;;          mov eax,[msg.wParam]         
;          mov rax,[msg.wParam]         
;          ret           
       ENDF
       
WndProc:
        FRAME hWnd,uMsg,wParam,lParam
        USES rbx,rdi,rsi
        Local hMemory,ps:PAINTSTRUCT,hdc
               
.WM_CREATE
        cmp D[uMsg],WM_CREATE
        jne >>.WM_CHAR       
        invoke GetDC, [hWnd]
        mov [hdc], rax             
        invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,NULL,\
                0,addr dwNeeded,addr dwReturned               
       invoke  GlobalAlloc, GHND,[dwNeeded]
       mov       [hMemory], rax
       invoke  GlobalLock, [rax]
       mov       [pinfo4],rax      
       invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,addr PrintCString,\
                                [dwNeeded],addr dwNeeded,addr dwReturned
        mov rbx,addr PrintCString
        mov rdx, [rbx+PRINTER_INFO_4.pPrinterName]
        invoke  CreateDC, NULL,rdx,NULL,NULL      
        mov       [hdcPrn],rax
        invoke  GlobalUnlock, [hMemory]   
        invoke  GlobalFree, [hMemory]                                                
        invoke Rectangle, [hdc],0,0,[holdright],[holdbottom]                    

; This code executed when turned on               
; temp code begin   
;tmsg2            db 'got to end of wm_create',0
;        invoke MessageBox, [hWnd], addr tmsg2, addr tmsg2, MB_OK ;true
; temp code end       

        xor rax,rax
        ret
       
.WM_CHAR         
        cmp D[uMsg],WM_CHAR 
        jne >>.WM_PAINT
;   other code
         ret
         
.WM_PAINT
        cmp D[uMsg],WM_PAINT
        jne >>.WM_DESTROY       

; This code never executes               
; temp code begin   
;tmsg3            db 'got wm_paint',0
        invoke MessageBox, [hWnd], addr tmsg3, addr tmsg3, MB_OK ;true
; temp code end       
Title: Re: 64 bit errors
Post by: qWord on October 04, 2012, 09:07:01 AM
- Why are using movable memory?
- For "mov rdx, [rbx+PRINTER_INFO_4.pPrinterName]", RBX seems to field with a wrong pointer.
- You should always check pointers after allocation (GlobalAlloc,HeapAlloc,...).

The following adaption works for me:
;#define LINKFILES
;#define codejps
#define WIN64
#INCLUDE headers\windows.h

DATA SECTION
    BufAdd          dd 0
    colorbk         dq 00ff0000h      ; blue
    pinfo4          dq 0
    hBrush          dq 0
    hdcPrn          dq 0
    hInstance       dq 0
    holdleft        dd 0
    holdright       dd 0
    holdbottom      dd 0
    holdtop         dd 0       
    savemiddleofX   dd 0
   
    AppName         db   "blah1",0
    datestring      db   "MM'-'dd'-'yyyy",0
    szDisplayName   db   'wc',0
    CommandLine     LPSTR ?

.code
start:
    and rsp,-16
    sub rsp,4*8
   invoke GetModuleHandleA, NULL
   mov    [hInstance],eax
   invoke GetCommandLine
   invoke WinMain, [hInstance],NULL,[CommandLine],SW_SHOWDEFAULT
   invoke ExitProcess,rax
WinMain: FRAME hInst,hPrevInst,CmdLine,CmdShow       
    LOCAL wc:WNDCLASSEXA,msg:MSG,hdc,rc:RECT,hWnd

    mov D[wc.cbSize], SIZEOF WNDCLASSEXA
    mov D[wc.style], CS_BYTEALIGNWINDOW | CS_HREDRAW | CS_VREDRAW
    mov rax,offset WndProc   
    mov Q[wc.lpfnWndProc],rax
    mov D[wc.cbClsExtra], NULL
    mov D[wc.cbWndExtra], NULL
    push [hInst]
    pop [wc.hInstance]
    invoke LoadIcon, NULL,IDI_APPLICATION
    mov Q[wc.hIcon], rax
    invoke LoadCursor, NULL,IDC_ARROW   
    mov Q[wc.hCursor], rax
    invoke CreateSolidBrush, [colorbk]          ; background color
    mov Q[hBrush], rax
    mov Q[wc.hbrBackground], rax
    mov Q[wc.lpszMenuName], NULL
    mov Q[wc.lpszClassName], OFFSET szDisplayName
    mov Q[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 ebx,2   ;
;   div ebx     ; bad code !!!
    shr eax,1
    mov [savemiddleofX],eax   
    mov eax,[rc.bottom]
    mov [holdbottom],eax
    mov eax,[rc.top]
    mov [holdtop],eax     

    invoke CreateWindow, addr szDisplayName,addr AppName,\
    WS_VISIBLE|WS_OVERLAPPEDWINDOW,\
    [rc.left],[rc.top],[rc.right],[rc.bottom],NULL,NULL,[hInstance],NULL                   
    mov [hWnd],rax                                 
    invoke ShowWindow, [hWnd],SW_SHOWNORMAL
    invoke UpdateWindow, [hWnd]

L1: invoke GetMessage,addr msg,0,0,0
    test eax,eax
    JZ >L2
    cmp eax,-1
    je >L2
    invoke TranslateMessage,addr msg
    invoke DispatchMessage,addr msg
    JMP L1
L2:
    ret
ENDF
   
WndProc: FRAME hWnd,uMsg,wParam,lParam
    USES rbx,rdi,rsi
    Local ps:PAINTSTRUCT,hdc,dwNeeded:Q,dwReturned:Q,rect:RECT
   
    .WM_CREATE
        cmp D[uMsg],WM_CREATE
        jne >> .WM_DESTROY

        mov Q[dwNeeded],0 ; zero upper 32 Bits

        invoke GetDC, [hWnd]
        mov [hdc], rax             
        invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,NULL,0,addr dwNeeded,addr dwReturned               
        invoke GlobalAlloc,GPTR,[dwNeeded]
        test rax,rax
        jz >> .err@GlobalAlloc
        mov [pinfo4],rax
        invoke  EnumPrinters,PRINTER_ENUM_LOCAL,NULL,4,[pinfo4],[dwNeeded],addr dwNeeded,addr dwReturned
        mov rbx,[pinfo4]
        mov rdx, [rbx+PRINTER_INFO_4.pPrinterName]
        invoke CreateDC, NULL,rdx,NULL,NULL       
        mov [hdcPrn],rax
     
        invoke Rectangle, [hdc],0,0,[holdright],[holdbottom]       
        jmp >> .END

        .err@GlobalAlloc
            ; allocation error
            invoke ExitProcess,0
        jmp >> .END
    .WM_DESTROY
        cmp D[uMsg],WM_DESTROY
        jne >> .WM_PAINT
        invoke GlobalFree, [pinfo4]
        invoke PostQuitMessage,0   
        jmp >> .END
    .WM_PAINT
        cmp D[uMsg],WM_PAINT
        jne >> .DEFAULT
        invoke GetClientRect,[hWnd],addr rect
        invoke BeginPaint,[hWnd],addr ps
        mov rcx,rax
        mov rdx,[pinfo4]
        invoke DrawText,rcx,Q[rdx+PRINTER_INFO_4.pPrinterName],-1,addr rect,DT_CENTER
        invoke EndPaint,[hWnd],addr ps
        jmp >> .END
    .DEFAULT
        invoke DefWindowProc,[hWnd],[uMsg],[wParam],[lParam]
        ret
    .END
   
    xor rax,rax
    ret
ENDF
Title: Re: 64 bit errors
Post by: shankle on October 05, 2012, 05:42:27 AM
Thanks qWord.
Working on your solution. Later I might have a few
questions. Just wanted to let you know I was not
ignoring your solution.
Title: Re: 64 bit errors
Post by: shankle on October 08, 2012, 12:17:54 AM
        10-7-2012
Program still errors out after painting the 1st screen.
I feel that it is some register change that I can not see in GoAsm.
Have no debugger to help me.
In MASM32 I avoided the stack like the plague. Only used it for
push/pop, pushad\popad. Savregx was much easier to follow.
So I do not really understand what "and rsp,-16 and sub rsp, 4*8"
are doing. I know that GoAsm adds rcx,rdx,r8 and R9 to the stack
but that is as far as I get at the present time in my learning curve.

In L1 what is cmp eax,-1 doing?
I noticed that you put GlobalFree in WM_DESTROY but did not use
GlobalLock in WM_CREATE. Is that OK??
Don't know how to do the fancy scroll goodie that you did.
Thanks for your help qWord       
       
#define LINKFILES
#define codejps
#define WIN64
#INCLUDE windows.h

DATA SECTION
colorbk              dq       00ff0000h      ; blue
dwNeeded         dq       0
dwReturned       dq       0
hBrush              dq       0
hdcPrn              dq       0
hInstance          dq       0
pinfo4               dq       0

BufAdd             dd       0
holdleft            dd       0
holdright          dd       0
holdbottom       dd       0
holdtop            dd       0       
savemiddleofX  dd       0

AppName            db   "blah1",0
datestring           db   "MM'-'dd'-'yyyy",0
szDisplayName    db   'wc',0
CommandLine LPSTR     ?

.code
start:
    and rsp,-16
    sub rsp,4*8
   invoke GetModuleHandleA, NULL
   mov    [hInstance],eax
   invoke GetCommandLine
   invoke WinMain, [hInstance],NULL,[CommandLine],SW_SHOWDEFAULT
   invoke ExitProcess,rax
                   
WinMain:
    FRAME hInst,hPrevInst,CmdLine,CmdShow       
   LOCAL wc:WNDCLASSEXA,msg:MSG,hdc,rc:RECT,hWnd

   mov   D[wc.cbSize], SIZEOF WNDCLASSEXA
   mov   D[wc.style], CS_BYTEALIGNWINDOW | CS_HREDRAW | CS_VREDRAW
   mov   rax,offset WndProc   
   mov   Q[wc.lpfnWndProc],rax
   mov   D[wc.cbClsExtra], NULL
   mov   D[wc.cbWndExtra], NULL
   push  [hInst]
   pop   [wc.hInstance]
   invoke LoadIcon, NULL,IDI_APPLICATION
   mov   Q[wc.hIcon], rax
    invoke LoadCursor, NULL,IDC_ARROW   
    mov   Q[wc.hCursor], rax
   invoke CreateSolidBrush, [colorbk]          ; background color
    mov   Q[hBrush], rax
   mov   Q[wc.hbrBackground], rax
   mov   Q[wc.lpszMenuName], NULL
   mov   Q[wc.lpszClassName], OFFSET szDisplayName
   mov   Q[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
     shr eax,1
     mov [savemiddleofX],eax       
     mov eax,[rc.bottom]
     mov [holdbottom],eax
     mov eax,[rc.top]
     mov [holdtop],eax     
                 
; This code executed when turned on
; temp code begin   
;tmsg1            db 'got to end of winmain_cr',0
;        invoke MessageBox, [hWnd], addr tmsg1, addr tmsg1, MB_OK ;true
; temp code end       

   INVOKE CreateWindow, addr szDisplayName,addr AppName,\
         WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX,\
        [rc.left],[rc.top],[rc.right],[rc.bottom],NULL,NULL,[hInstance],NULL                   
         mov   [hWnd],rax                                 

   invoke ShowWindow, [hWnd],SW_SHOWNORMAL
   invoke UpdateWindow, [hWnd]
; The above instruction executed and the screen appeared

L1:
    INVOKE GetMessageA,addr msg,0,0,0
    test eax,eax     ;see if it is WM_QUIT
    jz >L2           ;yes
    cmp eax,-1
    je >L2

    INVOKE TranslateMessage,addr msg
    INVOKE DispatchMessageA,addr msg
    jmp L1              ;after message dealt with, loop back for next one
L2:                     ;message was WM_QUIT
    ret
ENDF   

       
WndProc:
        FRAME hWnd,uMsg,wParam,lParam
        USES rbx,rdi,rsi
        Local hMemory,ps:PAINTSTRUCT,hdc
               
.WM_CREATE
        cmp D[uMsg],WM_CREATE
        jne >>.WM_CHAR       
        mov Q[dwNeeded],0             
        invoke GetDC, [hWnd]
        mov [hdc], rax
        invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,NULL,\
                0,addr dwNeeded,addr dwReturned               
       invoke  GlobalAlloc, GPTR,[dwNeeded]
       test    rax,rax
       jz >>.err@GlobalAlloc
          mov       [hMemory], rax
       invoke  GlobalLock, rax
       mov       [pinfo4],rax      
       invoke  EnumPrinters, PRINTER_ENUM_LOCAL,NULL,4,[pinfo4],\
                                [dwNeeded],addr dwNeeded,addr dwReturned
        mov rbx,[pinfo4]
        mov rdx, [rbx+PRINTER_INFO_4.pPrinterName]
        invoke  CreateDC, NULL,rdx,NULL,NULL      
       mov       [hdcPrn],rax
       invoke  GlobalUnlock, [hMemory]   
        invoke Rectangle, [hdc],0,0,[holdright],[holdbottom]                    

; This code executed when turned on               
; temp code begin   
;tmsg2            db 'got to end of wm_create',0
;        invoke MessageBox, [hWnd], addr tmsg2, addr tmsg2, MB_OK ;true
; temp code end       
        jmp >>.END
.err@GlobalAlloc
;    allocation error
         invoke ExitProcess,0
         jmp >>.END               
       
.WM_CHAR         
        cmp D[uMsg],WM_CHAR 
        jne >>.WM_PAINT
        jmp >>.END
         
.WM_PAINT
        cmp D[uMsg],WM_PAINT
        jne >>.WM_DESTROY       

; This code never executes               
; temp code begin   
;tmsg3            db 'got wm_paint',0
        invoke MessageBox, [hWnd], addr tmsg3, addr tmsg3, MB_OK ;true
; temp code end
        jmp >>.END

.WM_DESTROY
        cmp D[uMsg],WM_DESTROY
         jne >.default   
                         
       invoke  GlobalUnlock, [hMemory]     
       invoke  GlobalFree, [hMemory]                                                                             
        invoke ReleaseDC,[hWnd],[hdc]
        invoke PostQuitMessage,NULL
        jmp >>.END
.default
      invoke DefWindowProc,[hWnd],[uMsg],[wParam],[lParam]
       ret
.END
        xor rax, rax
        ret          
ENDF                 
Title: Re: 64 bit errors
Post by: qWord on October 08, 2012, 12:50:18 AM
Quote from: shankle on October 08, 2012, 12:17:54 AMSo I do not really understand what "and rsp,-16 and sub rsp, 4*8"
are doing.
Sorry, I did forget to remove these two instructions: They should align the stack to 16 and allocated the shadow space for the first 4 calling parameter (FASTCALL calling convention (http://msdn.microsoft.com/en-us/library/ms235286.aspx)). This is not needed, because GoAsm's INVOKE directive does this allready.
Quote from: shankle on October 08, 2012, 12:17:54 AMIn L1 what is cmp eax,-1 doing?
If GetMessage() fails, it returns -1.
Quote from: shankle on October 08, 2012, 12:17:54 AMI noticed that you put GlobalFree in WM_DESTROY but did not use
GlobalLock in WM_CREATE. Is that OK??
1. GlobalLock/Unlock is only needed, if you have an movable memory object - the example works with fixed memory -> GlobalAlloc (http://msdn.microsoft.com/en-us/library/windows/desktop/aa366574(v=vs.85).aspx)() returns a pointer instead of a handle. In fact, there is no reason to use movable memory, except that an API requires it (e.g. clip board operation).
2. The freeing is done in WM_DESTROY because the memory is used in WM_PAINT
Quote from: shankle on October 08, 2012, 12:17:54 AMDon't know how to do the fancy scroll goodie that you did.
Which scroll goodie?
Title: Re: 64 bit errors
Post by: wjr on October 08, 2012, 07:52:04 AM
Actually, more like the code at WM_PAINT is always executing... you return that you have processed the message, but you have not called BeginPaint and EndPaint (as qWord did), so the region does not get validated and you get another WM_PAINT request, over and over again...

Also, if you are going to use hMemory and hdc in WM_DESTROY, you will need to switch those variables from LOCAL to your DATA section (they will not be the same as they were while processing WM_CREATE).

Try Pelles C debugger mentioned in the other thread. Instead of MessageBox, you could use something like
INVOKE OutputDebugString, "Got to this point"
Title: Re: 64 bit errors
Post by: shankle on October 08, 2012, 01:51:58 PM
Thank you WJR.
The problem has been solved.
I was assuming that the error was prior to WM_PAINT
because my messagebox did NOT execute.
Anyway here is the offending instruction in WM_PAINT:
     FTS  db  0
    cmp B[FTS],0
    je >. blah1
    jmp >>.blah2
It took the branch to blah2 instead of blah1.
This is just info about why I was having all my problems.
Thanks for all your patience
Title: Re: 64 bit errors
Post by: shankle on October 13, 2012, 09:49:27 AM
                 10-12-2012
                                 
This code is for a 64-bit program.                 
purpose is to convert #s in spn to a string in hpn3
spn #s run like 1,2,3,4,5 etc. no sign involved.
hpn3 numbers convert to #01,#02,#03,#04 etc.
Needless to say it's not working in 64-bit GoAsm.
Almost the same code works in MASM32 and 32-bit GoAsm.

BufAdd      dd   0
spn         db   1
hpn3        db   "   ",0

       CALL Converter
                       
;other code       
Converter:     
;   edx  spn is the input field
;   ebx  hpn3 is the output field   
       lea ebx,hpn3     
       inc ebx                        ; save 1st byte for # sign
       mov [BufAdd],ebx
       xor edx,edx
       mov dl,B[spn]      ; input
       invoke dwtoa, edx,[BufAdd]    ; output is in hpn3                                   
       cmp B[hpn3+1],030h
        jge >
         mov B[hpn3+1],020h
:       
       mov B[hpn3],023h             ; # sign in front of number       
       inc B[spn]                   ; next input number
       ret
       
; other code       
; DWTOA is from MASM32
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: 64 bit errors
Post by: wjr on October 15, 2012, 04:55:44 AM
Try changing BufAdd to DQ and in Converter use ecx instead of edx...
Title: Re: 64 bit errors
Post by: shankle on October 15, 2012, 06:24:58 AM
Thanks to all that helped.
The 64-bit program is now working except for a few cosmetic
refinements.

I don't understand the reasoning behind using an 8 byte field to
handle a 1 byte field. I thought I was excessive by using a 4 byte
field to handle 1 byte. But this is 64-bit code and what do I know.