News:

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

Why this PROC freezes?

Started by frktons, September 04, 2010, 06:14:37 PM

Previous topic - Next topic

frktons

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


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

oex

No ret instruction

FormatNum PROC PtrNumber:DWORD

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

ret

FormatNum ENDP

We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

frktons

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
Mind is like a parachute. You know what to do in order to use it :-)

zemtex

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.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

frktons

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
Mind is like a parachute. You know what to do in order to use it :-)

zemtex

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
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

frktons

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

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

hutch--

 :bg

Magic rule, never mess up your CALL / RET pairing, it will come back to bite (BYTE ?) you later.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

zemtex

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
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

hutch--

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.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

zemtex

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.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

frktons

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
Mind is like a parachute. You know what to do in order to use it :-)