News:

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

Main Menu

error msg?

Started by shankle, June 26, 2012, 12:49:14 AM

Previous topic - Next topic

wjr

I do not get an error at my end with the required long jump, and unfortunately can not see why else an error would occur from what you have given.

If the L2 variation above does not work, then another way, since it looks like you are off by only 8 bytes, would be to avoid the long jump with shorter code... I do see some repetitive memory access that could be avoided with register usage if esi or edi were available and loaded with and then used instead of [holdR].

dedndave

i don't know if GoAsm uses processor directives or not
but, if he has it set for .386, it might cause troubles

shankle

#122
Not using ".386".

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

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

;in data section
colortxt         dd       00ffffffh      ; white

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

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

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

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

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





wjr

Although I saw it to Begin with, another potential cause of failure would be the hdc value, and tracing that back to the source gives this correction:

invoke BeginPaint, [hWnd], ADDR ps

shankle

Can't get this code to work in GoAsm.

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

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

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



satpro


; from the SystemTime structure

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

.ddd

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


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


;eeej defined in the data section

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

.ddd


[/size][size=78%]Would cmp ebx, [eeej] work for you?  (to compare what's in ebx to what's in eeej).  Again, in this case ebx IS a dword, so it only compares to dwords--no "D" needed here.[/size]

shankle

Hi Satpro,
Will give your suggestions a try.
The "moczx" wants a "D" in the  movzx instruction..
Then you have to put [] around eax.
Obviously I'm having syntax problems.

To [] or not to [].
To addr or [].
Changes from "if" to "cmp" is causing major problems.
Coming along, I now get my 1st screen and then
the message "My Prog has stopped working".
What I need to do is go from the 1st screen to "WM_CHAR"
to input data.
Yes I read the manual but not with 100% understanding.
Time will cure all I suppose.....

satpro

If the value in [stm.wDay] is a word then you code ->movzx ebx, W[stm.wDay].  It means you're moving a zero-extended WORD value into ebx.  It adds 16 zeroes to a word value.  If it was a byte you'd use a "B" and it would add 24 zeroes.  In GoAsm the use of brackets when addressing memory is mandatory.  Brackets around a register works the same.  No brackets around a register refers to what's in that register--not some address.  Let's say you do this:


DATA SECTION
GoAsm  dd  255


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


Now, to access variable [GoAsm] using esi:


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


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


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


Let's say:
GoAsm  dw  255 (WORD)


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



ADDR works with the address of some label.  It won't tell you what's in memory there.  That's what the brackets do.

jj2007

#128
Quote from: satpro on July 19, 2012, 11:50:33 AMGoAsm doesn't type-check, ...

GoAsm  dw  255 (WORD)

So would a simple inc [GoAsm] throw an error, or would it be encoded using a default size, i.e. DWORD? Masm and JWasm would use WORD in this case.

satpro

Hi jj,


It would give you a type expected (B,W, or D) error.

shankle

Thanks Satpro.
It worked just fine.

shankle

Got a lot of the bugs out of My Prog. It is now giving this message in WM_Create
using GetLastError code: "data area passed to a system call is to small".
The EnumPrinter has the cbBuf set to zero.
I tried to use "dwtoa" to find out what was in the pcbNeeded parameter
but it did not execute. I obviously have some [] or addr incorrect.
The DWTOA code is by WJR.

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

.code
; other goodies

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

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

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

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

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









dedndave

the idea is
1) call the function once to get the required buffer size by setting cbBuf to 0
2) allocate the buffer - size = cbNeeded
3) call the function again to fill the buffer - this time, pass a pointer to the buffer and it's size

it can be used with a pre-determined buffer the first time, of course
but - the code is probably simpler if you just get the size first

wjr

You are correct in where you are obviously incorrect. For a 32-bit program, (most) arguments passed to a function are 32-bit, so generally if they are looking for a string or a more complicated structure, what you pass to the function is a pointer to that string or structure. In GoAsm syntax, that would require something like ADDR SymbolName, so one correction is here:

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

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

invoke  EnumPrintersA, PRINTER_ENUM_LOCAL,NULL,4,NULL,0,\
                ADDR dwNeeded, ADDR dwReturned

dedndave

to add to what Wayne stated...

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

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

damned Hungarians   ;)