News:

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

Having a problem with using procs

Started by skywalker, April 17, 2006, 09:38:13 PM

Previous topic - Next topic

skywalker

I have studied some code with procedures.

I think I declared it OK, but I am not using it correctly. The compiler isn't liking those pushes either.


_WritePrivateProfileInt PROTO :DWORD, :DWORD, :DWORD, :DWORD

.data
      szKeyName     BYTE    "Wieviel",0          ; [Section]
      szValue       BYTE    "Nummer",0          ; Nummer=0E9h                         
                                     ; Null term string  Alt 233,234 0E9h 0EAh                                   
      iValue        BYTE    0E9h,00h
      szIniFile     BYTE    "c:\masm32\source\win1.ini",0
      valueOK       BYTE    "Value is OK.",0 
      Sample        BYTE    "Box",0

      szLu          BYTE    "%lu",0

.code

start:

invoke _WritePrivateProfileInt, ADDR szKeyName, ADDR szValue, ADDR iValue, ADDR szIniFile
fn GetPrivateProfileInt,Offset szKeyName,ADDR szValue,0,ADDR szIniFile

; the comparison is failing for some reason

.if EAX==0E9h   ;Show a message if stored value is OK

invoke MessageBox, 0, ADDR valueOK, ADDR Sample,MB_ICONINFORMATION

.endif

_WritePrivateProfileInt proc szKeyName:dword, szValue:dword, iValue:dword,
szIniFile:dword

        local   lpTempBuffer[16]:byte           ; temporary buffer

        lea     eax,lpTempBuffer                ;

        push    iValue                          ; value
        push    offset szLu                     ; format string
        push    eax                             ; output buffer
        call    wsprintfA                       ; format int
        pop     eax                             ;
        add     esp,4*2                         ; correct stack

        push    szIniFile                       ; ini filepath
        push    eax                             ; integer converted to string
        push    szValue                         ; value name
        push    szKeyName                       ; section
        call    WritePrivateProfileString

        ret
_WritePrivateProfileInt endp

    invoke ExitProcess,0

ramguru

Quote from: skywalker on April 17, 2006, 09:38:13 PM
I have studied some code with procedures.
I doubt it...
Quote from: skywalker on April 17, 2006, 09:38:13 PM
I think I declared it OK,
NO...
Quote from: skywalker on April 17, 2006, 09:38:13 PM
but I am not using it correctly.
WHY?
Quote from: skywalker on April 17, 2006, 09:38:13 PM
The compiler isn't liking those pushes either.
YES

I have some clues:
1. You're trying to convert (to string) an address this time;
2. You are not paying attention to error messages;
3. Your global variable names and proc variables names must differ.

P1

Once the Proc problem is solved.

I am locking this topic, because it's double posting to go on to the DATA TYPE problem.  And will refer you back to the original thread for your DATA TYPES problem.

Also understand, that push/pop are done in relation to DATA SIZE.  You are unbalanced on your pushes and pops, so you are corrupting your stack.  If you would use invoke, this ( pushes/pops ) would have been done for you.

Hint #1:  What are you returning to from your proc ???  Jump on the stack and take a look.  You will need a debugger, to see how this problem kills your program.  A simple analogy for the balancing of the stack is to think of it like a stair case going down ( or up ).  You go down the same number of stair steps, that you will come up later to be on the same floor, when you are done.  And microprocessors do not walk on thin air.

I admire your effort to format the data to output it, to fix the DATA TYPE problem.  But you could have used invoke for the code rather than to have clipped it from someone else's.  Use a debugger, and it will show you how the computer is handling the data, so you could make the proper adjustments to your code.  You went through all that trouble to format ( Type Conversion ) the data and you did nothing with it.

Procedures, the easy way.
Keep all procedures above the "start:" label.  This makes it so that you do not need to declare them with the proto statement.  Or add the proto statement in your code, but this does not fix your flow error.

Post your assembler errors ( ML output ) and we will walk you through each error.  When we get you past the assembly errors, which debugger are you using for the logical errors ???

Regards,  P1  :8)


skywalker

Quote from: P1 on April 17, 2006, 11:24:15 PM
Once the Proc problem is solved.

I am locking this topic, because it's double posting to go on to the DATA TYPE problem.  And will refer you back to the original thread for your DATA TYPES problem.

Also understand, that push/pop are done in relation to DATA SIZE.  You are unbalanced on your pushes and pops, so you are corrupting your stack.  If you would use invoke, this ( pushes/pops ) would have been done for you.

Hint #1:  What are you returning to from your proc ???  Jump on the stack and take a look.  You will need a debugger, to see how this problem kills your program.  A simple analogy for the balancing of the stack is to think of it like a stair case going down ( or up ).  You go down the same number of stair steps, that you will come up later to be on the same floor, when you are done.  And microprocessors do not walk on thin air.

I admire your effort to format the data to output it, to fix the DATA TYPE problem.  But you could have used invoke for the code rather than to have clipped it from someone else's.  Use a debugger, and it will show you how the computer is handling the data, so you could make the proper adjustments to your code.  You went through all that trouble to format ( Type Conversion ) the data and you did nothing with it.

Procedures, the easy way.
Keep all procedures above the "start:" label.  This makes it so that you do not need to declare them with the proto statement.  Or add the proto statement in your code, but this does not fix your flow error.

Post your assembler errors ( ML output ) and we will walk you through each error.  When we get you past the assembly errors, which debugger are you using for the logical errors ???

Regards,  P1  :8)


This is what I have now and it compiles without errors but returns 4206607 instead of E9h.
I use OllyDbg. What do you mean by logical errors?

I didn't clip the proc procedure from anyone, it was someone helping me out. I tried to find out where the post
came from(Wójcik) and ask him more questions, but wasn't sucessful.

I understand that the API expects either intergers or alphabetical strings only. I need to know how E9h
should be defined.


_WritePrivateProfileInt PROTO :DWORD, :DWORD, :DWORD, :DWORD

.data
      KeyName     BYTE    "Wieviel",0          ; [Section]
      SubKey       BYTE    "Nummer",0          ; Nummer=0E9h                         
      Value        DWORD    0E9h,00h ; Null term string  Alt 233=0E9h Alt 234=0EAh
      IniFile     BYTE    "c:\masm32\source\win1.ini",0
     
      valueOK       BYTE    "Value is OK.",0 
      Sample        BYTE    "Box",0

      szLu          BYTE    "%lu",0

.code

start:

invoke _WritePrivateProfileInt, ADDR KeyName, ADDR SubKey, ADDR Value, ADDR IniFile
fn GetPrivateProfileInt,Offset KeyName,ADDR Value,0,ADDR IniFile

; the comparison is failing for some reason

.if EAX==0E9h   ;Show a message if stored value is OK

invoke MessageBox, 0, ADDR valueOK, ADDR Sample,MB_ICONINFORMATION

.endif

invoke ExitProcess,0

_WritePrivateProfileInt proc szKeyName:dword, szValue:dword, iValue:dword,
szIniFile:dword

        local   lpTempBuffer[16]:byte           ; temporary buffer

        lea     eax,lpTempBuffer                ;

        push    iValue                          ; value
        push    offset szLu                     ; format string
        push    eax                             ; output buffer
        call    wsprintfA                       ; format int
        pop     eax                             ;
        add     esp,4*2                         ; correct stack

        push    szIniFile                       ; ini filepath
        push    eax                             ; integer converted to string
        push    szValue                         ; value name
        push    szKeyName                       ; section
        call    WritePrivateProfileString       ; section,key,string,filename

        ret
_WritePrivateProfileInt endp

jckl

Quote from: P1 on April 17, 2006, 11:24:15 PM
Procedures, the easy way.
Keep all procedures above the "start:" label.  This makes it so that you do not need to declare them with the proto statement.  Or add the proto statement in your code, but this does not fix your flow error.

I have a question on this for me.. Is it better to do it one way opposed to the other or does it not really make a difference? I have been using them below the start: label because i didnt know they could be put before it.

P1

Quote from: jckl on April 18, 2006, 05:14:47 PMIs it better to do it one way opposed to the other or does it not really make a difference?
No functional difference, but it takes less typing to do it the easy way.  The other way for larger programs is more self documenting.  Basically, It works just like if you 'include'd your extra code in another asm file above the start: label.

Quote from: jckl on April 18, 2006, 05:14:47 PMI have been using them below the start: label because i didnt know they could be put before it.
Between .code and start: for complete procedures in a single .asm file.

Regards,  P1  :8)

Light-I

Try to adopt this example (some variables may be missing) to convert integer to ASCII digits string :.data?
BuffDigitTmp db 32 dup (?)
DigitBase dd ?
.code
ReverseDigits:
push esi
lea esi, BuffDigitTmp ; this is reversed
.repeat
mov al, [esi + ecx - 1]
stosb
.untilcxz
xor eax, eax
stosb
pop esi
retn 0
Dword2DecTxt PROTO :LPSTR,:DWORD,:BOOL
; Size of lpszBuffDecTxt must be at least greater than 11(MaxNumber : 4294967295 0R -2147483647).
; Returns number of bytes written.
Dword2DecTxt proc lpszBuffDecTxt:LPSTR, DwordVal:DWORD, bSigned:BOOL
LOCAL bNegative:BOOL
LOCAL ediSave:DWORD
LOCAL SizeOfTxtOut:DWORD
;lpszBuffDecTxt can be NULL, function returns only number of out bytes
mov ediSave, edi
lea edi, BuffDigitTmp ; this will be stored in reversed rotation
mov bNegative, FALSE ; 0
mov eax, DwordVal
test eax, 80000000h ; sign test
.if !ZERO? && bSigned == TRUE
test eax, NOT 80000000h ; sign test
.if ZERO?   ; 7FFFFFFFh
xor eax, eax
.else
neg eax
.endif
inc bNegative ;  TRUE
.endif
mov DigitBase, 10
xor ecx, ecx
.repeat
xor edx, edx
div DigitBase
xchg al, dl
add al, "0"
stosb
mov al, dl
inc ecx
.until eax == 0
.if bNegative != FALSE
mov al, "-"
stosb
inc ecx
.endif
xor eax, eax
mov [edi], al
mov SizeOfTxtOut, ecx ; bytes written
mov edi, lpszBuffDecTxt
.if edi != NULL
call ReverseDigits
.endif
mov eax, SizeOfTxtOut ; number of bytes written will return in eax
mov edi, ediSave
ret
Dword2DecTxt endp
"lpszBuffDecTxt" can be NULL, regardless of it, procedure returns number of needed bytes for string...

P1

Quote from: Light-I on April 18, 2006, 09:45:14 PMTry to adopt this example (some variables may be missing) to convert integer to ASCII digits string
I would suggest you read all of skywalker's posts, to understand what you are trying to do.

Regards,  P1  :8)

Light-I

I've read a few of them (posts) - not enough time to read all - typicall using of copy & paste (everyone can start to try asm programming), but my post can help any other man too, who understand how processor works - my code havn't many comments included... ;)