News:

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

protecting proc with push and pop

Started by bcddd214, October 11, 2011, 12:02:43 AM

Previous topic - Next topic

bcddd214

I am trying to get this program to work that counts the number on letters in a string but trying to pass the data from one procedure to another via the esp register and protecting the data inside the procedure with push and pop but if I can even get it to work at all, my number count is off by 2???

bcddd214

Quote from: bcddd214 on October 11, 2011, 12:02:43 AM
I am trying to get this program to work that counts the number on letters in a string but trying to pass the data from one procedure to another via the esp register and protecting the data inside the procedure with push and pop but if I can even get it to work at all, my number count is off by 2???
INCLUDE Irvine32.inc

;################################################

.data

mes1      BYTE "Enter Your Name: ",0
inName      DWORD         0,0   
stringSize   BYTE         128 dup(0)
math1      BYTE         2

;################################################

.code


;################################################


getNameProc PROC
   push   edx
   mov      edx,offset      mes1
   call               WriteString
   mov      edx,offset      inName
   call               ReadString
   pop      edx
   ret
getNameProc ENDP

stringLengthProc PROC
   push   ebp
   mov      ebp,esp
   push   ecx
   push   edx
   mov      edi,[ebp+4]

;   mov    ecx,SIZEOF      inName
;   call                readString
;   mov    edx,OFFSET      stringSize
   call               writeString   
;   call                writedec
   
   pop      edx
   pop      ecx
   pop      ebp
   ret      4
stringLengthProc ENDP

main PROC
   call   getNameProc
   push    OFFSET inName
   call   stringLengthProc
   exit
main    ENDP

INVOKE  ExitProcess,0

END main

dedndave

   push   ebp
   mov      ebp,esp
   push   ecx
   push   edx
   mov      edi,[ebp+4]  ;try [ebp+8], instead


[EBP+0] points to the saved EBP value on the stack
[EBP+4] points to the RETurn address on the stack
[EBP+8] points to the PUSH'ed parameter

dedndave

another way to go is to make a prototype and let the assembler do all that stuff...
stringLengthProc PROTO :LPSTR

        .CODE

stringLengthProc PROC uses EDI lpString:LPSTR

        mov     edi,lpString

        ;some code

        ret

stringLengthProc ENDP

;to call it...

        INVOKE  stringLengthProc,offset mes1

NoCforMe

My suggestion: stay away from all that MOV EBP, ESP crap and messing around with EBP+x offsets; you'll only give yourself a headache.

Let the assembler keep track of all that stuff by using INVOKE and PROC. INVOKE pushes all the parameters on the stack, and PROC lets you refer to the passed parameters by name, instead of by some strange address like [EBP + 22]. Believe me, unless you comment your code religiously, you're going to be tearing your hair out trying to keep track of those "parameters". Use names instead. Much easier to follow.

Besides, in that code you posted, it looks like you could just as well pass values to that subroutine in registers (like EDX). You might consider that as the first choice, when there are only a few parameters (1-3) and you don't need those "scratch" registers ([EAX, ECX, EDX) for anything else.

MichaelW

Quote from: NoCforMe on October 11, 2011, 06:39:53 AM
Besides, in that code you posted, it looks like you could just as well pass values to that subroutine in registers (like EDX). You might consider that as the first choice, when there are only a few parameters (1-3) and you don't need those "scratch" registers ([EAX, ECX, EDX) for anything else.

If you need them for something else in the caller then you can preserve them around the call. If you need them for something else in the called procedure, once you have gotten the parameter values from them you are free to use them for whatever.

eschew obfuscation

drizz

Quote from: bcddd214 on October 11, 2011, 12:02:43 AM
my number count is off by 2???
I'm not experienced with Irvine's library but do check if the last two bytes are "13,10" or "CR,LF".
The truth cannot be learned ... it can only be recognized.

bcddd214

Quote from: dedndave on October 11, 2011, 12:34:56 AM
another way to go is to make a prototype and let the assembler do all that stuff...
stringLengthProc PROTO :LPSTR

        .CODE

stringLengthProc PROC uses EDI lpString:LPSTR

        mov     edi,lpString

        ;some code

        ret

stringLengthProc ENDP

;to call it...

        INVOKE  stringLengthProc,offset mes1


When trying to follow your recommendations I get wild errors:

INCLUDE Irvine32.inc

;################################################

.data

mes1      BYTE "Enter Your Name: ",0
inName      DWORD         0,0   
stringSize   BYTE         128 dup(0)
math1      BYTE         2

;################################################

stringLengthProc PROTO :LPSTR
.code


;################################################


getNameProc PROC
   push   edx
   mov      edx,offset      mes1
   call               WriteString
   mov      edx,offset      inName
   call               ReadString
   pop      edx
   ret
getNameProc ENDP


stringLengthProc PROC uses EDI lpString:LPSTR

   push   ebp
   mov      ebp,esp
   push   ecx
   push   edx
   mov      edi,lpstring
   mov      edi,[ebp+4]
;   mov    ecx,SIZEOF      inName
;   call                readString
;   mov    edx,OFFSET      stringSize
   call               writeString   
;   call                writedec
   
   pop      edx
   pop      ecx
   pop      ebp
   ret      4
stringLengthProc ENDP

main PROC
   call   getNameProc
   push    OFFSET inName
   call   stringLengthProc
   exit
main    ENDP

;INVOKE  ExitProcess,0
INVOKE  stringLengthProc,offset msg1

END main

errors:

Assembling: enterName.asm
enterName.asm(14) : error A2006: undefined symbol : LPSTR
enterName.asm(14) : error A2195: parameter or local cannot have void type
enterName.asm(14) : error A2131: VARARG parameter requires C calling convention
enterName.asm(32) : error A2006: undefined symbol : LPSTR
enterName.asm(32) : error A2195: parameter or local cannot have void type
enterName.asm(60) : error A2006: undefined symbol : msg1
enterName.asm(60) : error A2114: INVOKE argument type mismatch : argument : 1
enterName.asm(38) : error A2006: undefined symbol : lpstring
Press any key to continue . . .

dedndave

all those errors appear to be related to that one problem   :P

LPSTR is an alias for DWORD (at least, it is with masm32)
i did not realize you weren't using the masm32 package

try this...
stringLengthProc PROTO :DWORD

        .CODE

stringLengthProc PROC uses EDI lpString:DWORD

        mov     edi,lpString

        ;some code

        ret

stringLengthProc ENDP

;to call it...

        INVOKE  stringLengthProc,offset mes1

bcddd214

I AM using irvine 32 and make32 to compile

bcddd214

Quote from: bcddd214 on October 11, 2011, 11:57:10 PM
I AM using irvine 32 and make32 to compile

Same wild errors:

INCLUDE Irvine32.inc

;################################################

.data

mes1      BYTE "Enter Your Name: ",0
inName      DWORD         0,0   
stringSize   BYTE         128 dup(0)
math1      BYTE         2

;################################################

stringLengthProc PROTO :LPSTR
.code


;################################################


getNameProc PROC
   push   edx
   mov      edx,offset      mes1
   call               WriteString
   mov      edx,offset      inName
   call               ReadString
   pop      edx
   ret
getNameProc ENDP


stringLengthProc PROC uses EDI lpString:DWORD

   push   ebp
   mov      ebp,esp
   push   ecx
   push   edx
   mov      edi,lpstring
   mov      edi,[ebp+4]
;   mov    ecx,SIZEOF      inName
;   call                readString
;   mov    edx,OFFSET      stringSize
   call               writeString   
;   call                writedec
   
   pop      edx
   pop      ecx
   pop      ebp
   ret      4
stringLengthProc ENDP

main PROC
   call   getNameProc
   push    OFFSET inName
   call   stringLengthProc
   exit
main    ENDP

;INVOKE  ExitProcess,0
INVOKE  stringLengthProc,offset msg1

END main

dedndave

you did not change the PROTO parameter from LPSTR to DWORD

also, PROTO's generally go above the data section, but it isn't critical in this case

stringLengthProc PROTO :LPSTR
stringLengthProc PROTO :DWORD

dedndave

oh - also, the assembler takes care of EBP and RET (N) for you if you use this form
so, you want to modify the PROC like this...
stringLengthProc PROC uses EDI lpString:DWORD

   push   ecx
   push   edx
   mov      edi,lpstring
;   mov    ecx,SIZEOF      inName
;   call                readString
;   mov    edx,OFFSET      stringSize
   call               writeString   
;   call                writedec
   
   pop      edx
   pop      ecx
   ret

stringLengthProc ENDP

bcddd214

Almost there.
I have it pretty put together how it is supposed to work, but I am still missing something.

INCLUDE Irvine32.inc

;################################################

.data

mes1      BYTE "Enter Your Name: ",0
inName      DWORD         0,0   
stringSize   BYTE         128 dup(0)
math1      BYTE         2

;################################################

.code


;################################################


getNameProc PROC
    push    ebp
   mov     ebp, esp
   
   push   edx
   mov      edx,offset      mes1
   call               WriteString
   mov      edx,offset      inName
   mov     ecx, sizeof      inName
   call               ReadString
   pop      edx

   pop     ebp
   ret
getNameProc ENDP


stringLengthProc PROC

   push   ebp
   mov      ebp,esp
   push   ecx
   push   edx
   mov      edi,[ebp+8]
   call                  L1
L1:
   mov      ecx, 0
   mov      bl,[edi]
   cmp      bl, 0
   inc      ecx
   JE      L1Exit

   JMP      L1

L1Exit:
   
;   call                writedec
   
   pop      edx
   pop      ecx
   pop      ebp
   ret      4
stringLengthProc ENDP




main PROC
   call   getNameProc
   push    OFFSET inName
   call   stringLengthProc
   exit
main    ENDP

INVOKE  ExitProcess,0
;INVOKE  stringLengthProc,offset msg1

END main

dedndave

your input buffer for entring a name is 2 dwords ?
i think you intended it to be a 128 byte buffer

try this
        INCLUDE Irvine32.inc

;################################################

stringLengthProc PROTO :DWORD

;################################################

        .data

mes1    BYTE "Enter Your Name: ",0
inName  BYTE 128 dup(0) 

;################################################

        .code

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

getNameProc PROC

        push    edx
        mov     edx,offset mes1
        call    WriteString
        mov     edx,offset inName
        mov     ecx,sizeof inName
        call    ReadString
        pop     edx
        ret

getNameProc ENDP

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

stringLengthProc PROC lpString:DWORD

;returns the string length in EAX

        push    ecx
        push    edi
        mov     al,0
        or      ecx,-1
        mov     edi,lpString
        repnz   scasb
        or      eax,-2
        sub     eax,ecx
        pop     edi
        pop     ecx
        ret

stringLengthProc ENDP

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

main    PROC

        call    getNameProc
        INVOKE  stringLengthProc,offset inName
        call    WriteDec
        call    Crlf
        exit

main    ENDP

;################################################

        END     main