News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

MASM for FUN - #0.1 [msgbox]

Started by frktons, May 15, 2010, 09:46:02 AM

Previous topic - Next topic

frktons

Hi MASM masters,

I'm trying to figure out how to change this routine in order to display
the formatted number of cycles a routine takes.

The part to modify is the first part of the second line of text displayed by
MsgBox:


    .686                                    ; create 32 bit code
                                                ; for later processors
    .model flat, stdcall                    ; 32 bit memory model
    option casemap :none               ; case sensitive

    include c:\masm32\include\windows.inc     ; always first


  ; -----------------------------------------------------------------
  ; include files that have MASM format prototypes for function calls
  ; -----------------------------------------------------------------

    include c:\masm32\include\user32.inc
    include c:\masm32\include\kernel32.inc

  ; ------------------------------------------------
  ; Library files that have definitions for function
  ; exports and tested reliable prebuilt code.
  ; ------------------------------------------------

    includelib c:\masm32\lib\gdi32.lib
    includelib c:\masm32\lib\user32.lib
    includelib c:\masm32\lib\kernel32.lib

;--------------------------------------------------------------------


mb_ok     equ 0               ;mb_ok gets the value "0"
hWnd      equ 0               ;handler for the object
lpText    equ offset text     ;set a pointer to the text
lpCaption equ offset caption  ;set a pointer to the caption


; here we have our Data

.Data                                       
text     db "Hey Dude! your routine has taken some",13,10 ; first row of the text(with word-wrap)
            db "xxx,xxx,xxx,xxx,xxx CPU cycles! Are you satisfied?",0
                                ; second row, terminated with "0"

caption  db "ASM Performance Test",0 ;Captionstring, 0-terminated


; and here we start with our code

.Code                                 
Main:
          ; let's display the results   :))

        push mb_ok              ;PUSH value for uType
        push lpCaption          ;PUSH Pointer to Caption
        push lpText                ;PUSH Pointer to Text
        push hWnd                ;PUSH Masterhandle
        call MessageBoxA        ;CALL MessageBoxA
        CALL    ExitProcess     ;End (exit) program

End Main                        ;End of code

;-----------------------------------END--------------------------------


How can I manage this part of the string:

db "xxx,xxx,xxx,xxx,xxx CPU cycles! Are you satisfied?",0
                                ; second row, terminated with "0"

to replace "xxx,xxx,xxx,xxx,xxx" with the formatted number string obtained elsewhere?

Thanks

Frank
Mind is like a parachute. You know what to do in order to use it :-)

Vortex

A quick example for you to give an idea :


include GetCompName.inc

NAME_BUFF_SIZE = MAX_COMPUTERNAME_LENGTH + 1

.data

nSize       dd NAME_BUFF_SIZE
format1     db 'The computer name = %s',0
capt        db 'Hello',0

.data?

NameBuffer  db NAME_BUFF_SIZE dup(?)
buffer2     db 100 dup(?)

.code

start:

    invoke  GetComputerName,ADDR NameBuffer,ADDR nSize

    invoke  wsprintf,ADDR buffer2,ADDR format1,ADDR NameBuffer
    invoke  MessageBox,0,ADDR buffer2,ADDR capt,MB_OK

    invoke  ExitProcess,0

END start

frktons

Quote from: Vortex on May 15, 2010, 10:01:23 AM
A quick example for you to give an idea :


include GetCompName.inc

NAME_BUFF_SIZE = MAX_COMPUTERNAME_LENGTH + 1

.data

nSize       dd NAME_BUFF_SIZE
format1     db 'The computer name = %s',0
capt        db 'Hello',0

.data?

NameBuffer  db NAME_BUFF_SIZE dup(?)
buffer2     db 100 dup(?)

.code

start:

    invoke  GetComputerName,ADDR NameBuffer,ADDR nSize

    invoke  wsprintf,ADDR buffer2,ADDR format1,ADDR NameBuffer
    invoke  MessageBox,0,ADDR buffer2,ADDR capt,MB_OK

    invoke  ExitProcess,0

END start


OK. Thanks, Vortex.

In order to learn something I have to dissect any single line and try to
understand its meaning.

so:

include GetCompName.inc

are the usual Includes. No problem.  :P


NAME_BUFF_SIZE = MAX_COMPUTERNAME_LENGTH + 1

this should be a MASM directive or EQUATE to make one variable name
means something else. Isn't it?  ::)


.data

nSize       dd NAME_BUFF_SIZE
format1     db 'The computer name = %s',0
capt        db 'Hello',0

Here we have some variable declarations and initializations before CALLing
Windows APIs. Is it true?
::)


.data?

NameBuffer  db NAME_BUFF_SIZE dup(?)
buffer2     db 100 dup(?)

here you use a different method than the one I was trying to implement,
you use uninitialized variables, while I was thinking about replacing bytes
in an initialized variable.


start:

    invoke  GetComputerName,ADDR NameBuffer,ADDR nSize

You are CALLing an API to get the Computer Name, passing it 2 ADDRESSES
for the buffer and the size [MAX_COMPUTERNAME_LENGTH + 1].


    invoke  wsprintf,ADDR buffer2,ADDR format1,ADDR NameBuffer

This one is another API CALL but I actually don't know what it does,  :(
or why we have to use it before CALLing MsgBox.


    invoke  MessageBox,0,ADDR buffer2,ADDR capt,MB_OK

    invoke  ExitProcess,0

eventually you CALL the MsgBox with the strings to display and
exit after that.

Would you correct and explain the points I didn't get?

Thanks

Frank



Mind is like a parachute. You know what to do in order to use it :-)

Vortex

The buffer to receive the computer name should have a size of MAX_COMPUTERNAME_LENGTH + 1 characters :

http://msdn.microsoft.com/en-us/library/ms724295%28VS.85%29.aspx

NAME_BUFF_SIZE = MAX_COMPUTERNAME_LENGTH + 1

MAX_COMPUTERNAME_LENGTH is expanded to the actual value 15 and NAME_BUFF_SIZE becomes 15 + 1 = 16

Quote
Here we have some variable declarations and initializations before CALLing
Windows APIs. Is it true?

Yes, that's true.


.data?

NameBuffer  db NAME_BUFF_SIZE dup(?)
buffer2     db 100 dup(?)


They are uninitialized variables to receive the computer name and the formatted string created by wsprintf.


invoke  wsprintf,ADDR buffer2,ADDR format1,ADDR NameBuffer


Quote
The wsprintf function formats and stores a series of characters and values in a buffer. Any arguments are converted and copied to the output buffer according to the corresponding format specification in the format string. The function appends a terminating null character to the characters it writes, but the return value does not include the terminating null character in its character count.

format1     db 'The computer name = %s',0

wsprintf replaces %s with the computer name.

frktons

Thanks Vortex, everything should be clear now.  :U

As I was working on the replacement task of the text to be displayed inside the
MsgBox, I eventually came up with this first sample:


;--------------------------------------------------------------------
; MsgBox displaying messages about routine performance
;--------------------------------------------------------------------

    .686                                                             ; create 32 bit code
                                                                         ; for later processors
    .model flat, stdcall                                     ; 32 bit memory model
    option casemap :none                                ; case sensitive

    include c:\masm32\include\windows.inc     ; always first


  ; -----------------------------------------------------------------
  ; include files that have MASM format prototypes for function calls
  ; -----------------------------------------------------------------

    include c:\masm32\include\user32.inc
    include c:\masm32\include\kernel32.inc

  ; ------------------------------------------------
  ; Library files that have definitions for function
  ; exports and tested reliable prebuilt code.
  ; ------------------------------------------------

    includelib c:\masm32\lib\gdi32.lib
    includelib c:\masm32\lib\user32.lib
    includelib c:\masm32\lib\kernel32.lib

;--------------------------------------------------------------------


mb_ok     equ 0               ;mb_ok gets the value "0"
hWnd      equ 0               ;handler for the window
lpText    equ offset text     ;set a pointer to the text
lpCaption equ offset caption  ;set a pointer to the caption


; here we have our Data

.Data                                       
text     db "Hey Dude! your routine has taken some",13,10 ; first row of the text(with word-wrap)
         db "xxx,xxx,xxx,xxx,xxx CPU cycles! Are you satisfied?",0
                                    ; second row, terminated with "0"
fnum     db "371,568,905,207,572 "  ; formatted number to display
dist_txt dd 39                      ; distance from the beginning of "text" string to replace
len_txt  dd 20                      ; lenght [number] of bytes to replace
                               

caption  db "ASM Performance Test",0 ;Captionstring, 0-terminated


; and here we start with our code

.Code                                 
Main:
; lets display the results   :))

time_to_replace:

   mov edx,offset text            ; address of text
   add edx,39                           ; starting point to replace into "text" string

   mov esi,offset fnum            ; address of "fnum" with the formatted number
   mov ecx,20                           ; number of bytes to replace

replacing_task:

   mov eax,[esi]                  ; getting 4 bytes from the formatted string number
   mov [edx],eax                 ; moving them to the text to be displayed



   add esi,4                         ; moving 4 bytes forward
   add edx,4                        ; into both source and target string   

   sub ecx,4                        ; managing the counter loop to see if I moved them all


   jnz replacing_task         ; if not all of them moved do it again



display_box:
             

push mb_ok              ;PUSH value for uType
push lpCaption          ;PUSH Pointer to Caption
push lpText             ;PUSH Pointer to Text
push hWnd               ;PUSH Masterhandle
call MessageBox         ;CALL MessageBox
CALL    ExitProcess     ;End (exit) program

End Main                        ;End of code

;-----------------------------------END--------------------------------


Strangely enough it seems to work.   :lol

But it is very limited, as it only replaces and displays a 20 bytes formatted number string.

This limit is due to the fact I'm using the .data with fixed lenght variables
already initialized. I have to use uninitialized variables in the .data? section
in order to have a more generalized routine with variable lenght of data to display.

Working on it with all the samples you guys have provided.  :P

Frank


Mind is like a parachute. You know what to do in order to use it :-)

Ghandi

You coud always go with using format strings (even ones you just concatenate with your results to make larger strings) and allocated memory, that way your string length limits are only those imposed by memory and Windows itself. This idea seems clunky though and inefficient.

HR,
Ghandi