The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: frktons on September 04, 2010, 06:14:37 PM

Title: Why this PROC freezes?
Post by: frktons on September 04, 2010, 06:14:37 PM
When I call a PROC this way:

INVOKE FormatNum,PtrMyString


the program freezes, like a general fault page

What's wrong in this program? As it is it works, but if I call FormatNum
it freaks out.

;---------------------------------------------------------------------------------
; MACRO ustrv$
;---------------------------------------------------------------------------------
; A new macro that converts an unsigned integer to a string
; using a call to function crt__ultoa.
; This is a modifies version of ustr$ macro of MASM32 package.
; The difference is that the string to fill is defined in the
; Main program and the content of it can be used for later
; needs.
;---------------------------------------------------------------------------------


include \masm32\include\masm32rt.inc

FormatNum PROTO :DWORD

ustrv$ MACRO DDvalue1, DDvalue2   ;; unsigned integer to string
     invoke crt__ultoa,DDvalue1,DDvalue2,10
     EXITM <offset DDvalue2>
ENDM

;---------------------------------------------------------------------------------
.data

MyString      DB  20 dup (0),0
PtrMyString   DD  MyString
NumToFormat   DD  3123456789

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

Sep         DB  ",",0   ;   used for decimal numbers separator - choose yours
lpSep       DD  Sep     ;   When calling GetNumberFormat
Tsep        DD  ".",0   ;   used for thousand numbers separator - choose yours
lpTsep      DD  Tsep    ;   When calling GetNumberFormat

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

.data?

Buffer      DB  255 dup(?)     ; used by GetNumberFormat
NumFmt      NUMBERFMT <>       ; to format with thousand separator integer numbers

;---------------------------------------------------------------------------------
; Structure for number formatting
;---------------------------------------------------------------------------------   
; NUMBERFMTA STRUCT
;    NumDigits         DWORD      ?
;    LeadingZero       DWORD      ?
;    Grouping          DWORD      ?
;    lpDecimalSep      DWORD      ?
;    lpThousandSep     DWORD      ?
;    NegativeOrder     DWORD      ?
; NUMBERFMTA ENDS
;
; NUMBERFMT  equ  <NUMBERFMTA>     
;---------------------------------------------------------------------------------

.code
start:

;----------------------------------------------------------------------------------------------------
; Initialize structure for calling GetNumberFormat
;----------------------------------------------------------------------------------------------------

mov NumFmt.NumDigits, 0               ; 0 for No decimal digits
mov NumFmt.LeadingZero, 0             ; 0 = No leading zeroes
mov NumFmt.Grouping, 3                ; Groups of three numbers
mov NumFmt.lpDecimalSep,  offset Sep  ; Pointer to NULL terminated string with the decimal separator
mov NumFmt.lpThousandSep, offset Tsep ; Pointer to NULL terminated string with the thousand separator
mov NumFmt.NegativeOrder, 0           ; Negative number mode

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

print "The number "
print ustr$(NumToFormat)
print " is string: "

mov PtrMyString, ustrv$(NumToFormat, offset MyString)

print PtrMyString,13,10,13,10

print "The formatted number is: "

invoke GetNumberFormat, NULL, 0, PtrMyString, offset NumFmt, offset Buffer, 255

; INVOKE FormatNum,PtrMyString ; <--------------- calling this PROC the program gives a GPF and freezes

print offset Buffer,13,10,13,10


inkey " -- ok --"

exit


;----------------------------------------------------------------------------------------------------
; Procedure for formatting a string with thousand comma/point separator
;----------------------------------------------------------------------------------------------------


FormatNum PROC PtrNumber:DWORD

  invoke GetNumberFormat, NULL, 0, PtrNumber, offset NumFmt, offset Buffer, 255

FormatNum ENDP

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

end start


Title: Re: Why this PROC freezes?
Post by: oex on September 04, 2010, 06:24:54 PM
No ret instruction

FormatNum PROC PtrNumber:DWORD

  invoke GetNumberFormat, NULL, 0, PtrNumber, offset NumFmt, offset Buffer, 255

ret

FormatNum ENDP

Title: Re: Why this PROC freezes?
Post by: frktons on September 04, 2010, 06:40:29 PM
Quote from: oex on September 04, 2010, 06:24:54 PM
No ret instruction

FormatNum PROC PtrNumber:DWORD

  invoke GetNumberFormat, NULL, 0, PtrNumber, offset NumFmt, offset Buffer, 255

ret

FormatNum ENDP

Thanks oex, being an advanced n00bist I didn't figure it myself  :lol

Frank
Title: Re: Why this PROC freezes?
Post by: zemtex on September 04, 2010, 06:58:57 PM
Yes, there is no ret instruction. The program just continues to execute random instructions passed the function, which may be filled up with 0 and NOP instructions, eventually crashing the program. The ret instruction corrects the stack, pops the return address off the stack (Which is the address of the next instruction after the initial call) and then continues normally. Technically speaking you don't need to use ret, you can also use pop and then return manually.

Using call instead of invoke help you to remember the stack. Invoke is good to use, but it make it easy to forget the nature of the stack.
Title: Re: Why this PROC freezes?
Post by: frktons on September 04, 2010, 08:18:04 PM
Quote from: zemtex on September 04, 2010, 06:58:57 PM
Yes, there is no ret instruction. The program just continues to execute random instructions passed the function, which may be filled up with 0 and NOP instructions, eventually crashing the program. The ret instruction corrects the stack, pops the return address off the stack (Which is the address of the next instruction after the initial call) and then continues normally. Technically speaking you don't need to use ret, you can also use pop and then return manually.

Using call instead of invoke help you to remember the stack. Invoke is good to use, but it make it easy to forget the nature of the stack.

Interesting  :U

Could you please post the variations to use call insted of invoke?
In this way I can "see" what you mean with push/pop the stack
instead of ret.
Thanks
Title: Re: Why this PROC freezes?
Post by: zemtex on September 04, 2010, 09:08:56 PM
It is possible, but I wouldnt do it.  :bdg

You could just pop off the address and do a short or far jump to that address..

When using call, make sure you push the last argument first.

Function Arg1 Arg2 Arg3

push arg3
push arg2
push arg1
call [eax]

if you watch the program in olly you can see the pushes made. I assume you're no news so I wont take it further haha
Title: Re: Why this PROC freezes?
Post by: frktons on September 04, 2010, 09:12:49 PM
Quote from: zemtex on September 04, 2010, 09:08:56 PM
It is possible, but I wouldnt do it.  :bdg

You could just pop off the address and do a short or far jump to that address..

When using call, make sure you push the last argument first.

Function Arg1 Arg2 Arg3

push arg3
push arg2
push arg1
call [eax]

if you watch the program in olly you can see the pushes made. I assume you're no news so I wont take it further haha

Well done zemtex  :U

As somebody once said: Never begin something that you cannot finish.

I'm used to finish what I start, by the way.  :lol

Title: Re: Why this PROC freezes?
Post by: hutch-- on September 07, 2010, 05:57:36 AM
 :bg

Magic rule, never mess up your CALL / RET pairing, it will come back to bite (BYTE ?) you later.
Title: Re: Why this PROC freezes?
Post by: zemtex on September 07, 2010, 08:35:39 AM
Quote from: hutch-- on September 07, 2010, 05:57:36 AM
:bg

Magic rule, never mess up your CALL / RET pairing, it will come back to bite (BYTE ?) you later.
I agree as a general rule. But it is not an absolute MUST to do so. Here are a few samples where you dont need to pair them up:

1: If you're planning to run en eternal loop from program start to program end.
2: If the function is invoking exitprocess and returning to the operating system
3: If you manually correct the stack and jump back again
4: If the next instruction after the function is an int3 instruction / breakpoint
5: or if the next instruction after the function stalls the thread
Title: Re: Why this PROC freezes?
Post by: hutch-- on September 07, 2010, 11:54:14 AM
On the exit from a program nothing matters much but for code executed in an environment where speed matters and code keeps running, it is a mistake to do this. It easy enough to code writing a location on the stack from either a CALL mnemonic or an absolute address and then jumping to it but if that algo gets run regularly you go beyond the depth of the call/ret cache and will pay a performance penalty.
Title: Re: Why this PROC freezes?
Post by: zemtex on September 07, 2010, 12:30:31 PM
It is not recommended at all, we're talking mere semantics of code execution. I never do that kind of stuff, or at least not on a regular basis.

I guess my main point is that one ought to get familiar with "going around" the standard way of doing things, it greatly helps to understand
the "wrapper" of masm so that you dont always look at the standard with a questionmark in your eye.

Gotta experiment and try different things once in a while to see how stuff works.
Title: Re: Why this PROC freezes?
Post by: frktons on September 07, 2010, 12:36:37 PM
Quote from: zemtex on September 07, 2010, 12:30:31 PM
It is not recommended at all, we're talking mere semantics of code execution. I never do that kind of stuff, or at least not on a regular basis.

I guess my main point is that one ought to get familiar with "going around" the standard way of doing things, it greatly helps to understand
the "wrapper" of masm so that you dont always look at the standard with a questionmark in your eye.

Gotta experiment and try different things once in a while to see how stuff works.

Both of you agree to stick with standard rules in order not to get biten by unwanted stuff.

And at the same time, experimenting different ways of doing things can help to have
a wider look of the matter.

Thanks to both

Frank