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?
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).
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
DI is a 16 Bit register -> rename your locale variable.
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.
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
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).
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
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
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.
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.
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
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.
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
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).
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.
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
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.
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.
you maybe show us you current code?
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
- 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
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.
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
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?
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"
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
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
Try changing BufAdd to DQ and in Converter use ecx instead of edx...
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.