News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

64 bit errors

Started by shankle, September 14, 2012, 10:32:05 PM

Previous topic - Next topic

shankle

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?

wjr

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).

shankle

         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                           
             
       

                       

qWord

DI is a 16 Bit register -> rename your locale variable.
MREAL macros - when you need floating point arithmetic while assembling!

wjr

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.

shankle

#5
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   
   
   
       

wjr

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).

shankle

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

wjr

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

shankle

#9
   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.

wjr

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.

shankle

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

wjr

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.

shankle

         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       

wjr

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).