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


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


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


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
        FRAME  hWnd,iMsg,wParam,lParam
        USES ebx,edi,esi
        Local hMemory,stm:SYSTEMTIME,ps:PAINTSTRUCT,hdc,hdcPrn

        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)

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


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


Can't get this code to work in GoAsm.

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

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

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


; from the SystemTime structure

xor ebx,ebx
mov bx, [stm.wDay]          ; or: movzx ebx, W[stm.wDay] and eliminate the xor code
; 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


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


[/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]


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


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:

GoAsm  dd  255

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.


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.


Hi jj,

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


Thanks Satpro.
It worked just fine.


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.

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

; other goodies

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

;   test begin
;   edx is the input field
;   ebx  convfld  is the output field 
    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
;   test end
        jmp >>.default
; other goodies

;code per WJR
     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
      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


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


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


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