The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: bcddd214 on October 25, 2011, 08:09:52 PM

Title: Calling from a proc
Post by: bcddd214 on October 25, 2011, 08:09:52 PM
I have this program and trying to change the calling in stringLength instead of calling from main and getting some wild errors

Line 54 is what I moved.

Title               flipTest
INCLUDE Irvine32.inc

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

SwapIt           PROTO :DWORD,:DWORD
stringLengthProc PROTO :DWORD

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

.data

mes1      BYTE "Enter a 5 digit string: ",0
inName      DWORD         3 dup(0)
math1      BYTE         2
lpString:DWORD
dwLength:DWORD

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

.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
      call   SwapIt offset inName,eax
        ret

stringLengthProc ENDP

;************************************************

SwapIt  PROC

   push   ecx
   push   edx
    mov     ecx,dwLength
    mov     edx,lpString
    dec     ecx
    add     ecx,edx
    jmp short SwpIt1

SwpIt0: mov     al,[edx]
    mov     ah,[ecx]
    mov     [ecx],al
    mov     [edx],ah
    dec     ecx
    inc     edx

SwpIt1: cmp     ecx,edx
    ja      SwpIt0
   pop      edx
   pop      ecx
    ret

SwapIt  ENDP

;************************************************

main PROC

        call    getNameProc
        INVOKE  stringLengthProc,offset inName
;        INVOKE  SwapIt,offset inName,eax
        mov     edx,offset inName
        call    WriteString
        call    Crlf
        exit

main    ENDP

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

END main
Title: Re: Calling from a proc
Post by: jj2007 on October 25, 2011, 08:40:47 PM
Why do you believe that the assembler should understand call SwapIt offset inName,eax ?
Title: Re: Calling from a proc
Post by: dedndave on October 25, 2011, 08:57:11 PM
i would be surprised if it assembles   :P
     call   SwapIt offset inName,eax

you are trying to convert a process that has paramaters on the stack to one that does not
to be tidy, let's reorganize things a bit
notice how the SwapIt proc now calls StringLength, so it is "self-contained"
made a few other changes to make it easier to read   :P

        TITLE   FlipTest
        INCLUDE Irvine32.inc

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

        .DATA

Mes1    BYTE "Enter a 5 digit string: ",0
InName  BYTE 6 dup(0)

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

        .CODE

;************************************************

GetInput PROC

;Call With: EAX = address displayed string
;           EDX = address of input buffer
;           ECX = size of input buffer
;
;  Returns: buffer filled with user input
;           all registers are preserved

        push    edx
        mov     edx, eax
        call    WriteString
        pop     edx
        call    ReadString
        ret

GetInput ENDP

;************************************************

StringLength PROC

;Call With: EDX = address of string
;
;  Returns: ECX = length of string, less null terminator
;           all other registers preserved

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

StringLength ENDP

;************************************************

SwapIt  PROC

;Call With: EDX = address of string to reverse
;
;  Returns: string is reversed
;           all registers are preserved

        push    eax
        push    ecx
        push    edx
        call    StringLength
        dec     ecx
        add     ecx, edx
        jmp short SwpIt1

SwpIt0: mov     al, [edx]
        mov     ah, [ecx]
        mov     [ecx], al
        mov     [edx], ah
        dec     ecx
        inc     edx

SwpIt1: cmp     ecx, edx
        ja      SwpIt0

        pop     edx
        pop     ecx
        pop     eax
        ret

SwapIt  ENDP

;************************************************

Main    PROC

        mov     eax, offset Mes1
        mov     edx, offset InName
        mov     ecx, sizeof InName
        call    GetInput
        call    SwapIt
        call    WriteString
        call    Crlf
        exit

Main    ENDP

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

        END     Main


EDIT: changed the proc called "GetName" to "GetInput" - makes more sense

the forum seems to want to remove a space from each line that starts with one, today - fixed that too
Title: Re: Calling from a proc
Post by: bcddd214 on October 25, 2011, 11:10:58 PM
But SwapIt cannot occur in main. It has to be called from the 'StringLength PROC'???
Title: Re: Calling from a proc
Post by: bcddd214 on October 25, 2011, 11:41:44 PM
it quits working like this

        TITLE   FlipTest
        INCLUDE Irvine32.inc

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

        .DATA

Mes1    BYTE "Enter a 5 digit string: ",0
InName  BYTE 6 dup(0)

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

        .CODE

;************************************************

GetInput PROC

;Call With: EAX = address displayed string
;           EDX = address of input buffer
;           ECX = size of input buffer
;
;  Returns: buffer filled with user input
;           all registers are preserved

        push    edx
        mov     edx, eax
        call    WriteString
        pop     edx
        call    ReadString
        ret

GetInput ENDP

;************************************************

StringLength PROC

;Call With: EDX = address of string
;
;  Returns: ECX = length of string, less null terminator
;           all other registers preserved

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

StringLength ENDP

;************************************************

SwapIt  PROC

;Call With: EDX = address of string to reverse
;
;  Returns: string is reversed
;           all registers are preserved

        push    eax
        push    ecx
        push    edx
        call    StringLength
      call    SwapIt
        dec     ecx
        add     ecx, edx
        jmp short SwpIt1

SwpIt0: mov     al, [edx]
        mov     ah, [ecx]
        mov     [ecx], al
        mov     [edx], ah
        dec     ecx
        inc     edx

SwpIt1: cmp     ecx, edx
        ja      SwpIt0

        pop     edx
        pop     ecx
        pop     eax
        ret

SwapIt  ENDP

;************************************************

Main    PROC

        mov     eax, offset Mes1
        mov     edx, offset InName
        mov     ecx, sizeof InName
        call    GetInput
;        call    SwapIt
        call    WriteString
        call    Crlf
        exit

Main    ENDP

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

        END     Main
Title: Re: Calling from a proc
Post by: dedndave on October 26, 2011, 01:11:48 AM
i am afraid i do not understand what you are trying to accomplish

did the code work, as i posted it ?

what are you trying to do - be specific
Title: Re: Calling from a proc
Post by: bcddd214 on October 28, 2011, 12:42:23 AM
I made some changes so my format is now correct but the program quit working.
I had to change over to work my counting out on the ecx register but this broke my swapping action. I tried to do a static flip back to the eax but mov'ing my data from ecx back to eax is not working.
Line 57 "should" be the point that the program passes my info back to eax and then carry on as normal.
Not sure what to do at this point.

***************************
        TITLE   FlipTest
        INCLUDE Irvine32.inc

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

        .DATA

Mes1    BYTE "Enter a 5 digit string: ",0
InName  BYTE 6 dup(0)

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

        .CODE

;************************************************

GetInput PROC

        push    edx
        mov     edx, eax
        call    WriteString
        pop     edx
        call    ReadString
        ret

GetInput ENDP

;************************************************

StringLength PROC
      push ebp
      mov      ebp, esp
        push    edi
        mov     al, 0
        or      ecx, -1
        mov     edi, [ebp+8]
        repnz   scasb
        neg     ecx
        sub     ecx, 2
      mov      eax, ecx
        pop     edi
      pop      ebp
        ret   4

StringLength ENDP

;************************************************

SwapIt  PROC
        push    ebp
      mov     ebp, esp
        push    eax
        push    ecx
        push    edx      
      push    [ebp + 8]
      call    StringLength
      mov      ecx, eax
        dec     ecx      
        add     ecx, edx
        jmp short SwpIt1

SwpIt0: mov     al, [edx]
        mov     ah, [ecx]
        mov     [ecx], al
        mov     [edx], ah
        dec     ecx
        inc     edx

SwpIt1: cmp     ecx, edx
        ja      SwpIt0

        pop     edx
        pop     ecx
        pop     eax
      pop     ebp
        ret

SwapIt  ENDP

;************************************************

Main    PROC

        mov     eax, offset Mes1
        mov     edx, offset InName
        mov     ecx, sizeof InName
        call    GetInput

      push    OFFSET InName
;        call    SwapIt
      call   StringLength
;      call   writedec
        call    WriteString
        call    Crlf
        exit

Main    ENDP

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

        END     Main
Title: Re: Calling from a proc
Post by: dedndave on October 28, 2011, 01:52:20 AM
ok - let's go back to the code in this post

http://www.masm32.com/board/index.php?topic=17611.msg148268#msg148268

at the beginning of each PROC, i made notes on what registers are passed, returned, and preserved
unless a value is returned in a specific register, i preserved it
there are exceptions to this - if the value in that register is no longer useful
read those notes carefully
the changes you made destroy the contents of ECX and maybe EDX, which were intended to be preserved
in my posted code - the values in those registers are used in the next call - maybe even the one after

and - a big problem - you do not want to CALL SwapIt inside the SwapIt PROC
that routine will not exit until the stack overflows   :P
Title: Re: Calling from a proc
Post by: tenkey on October 28, 2011, 03:42:23 PM
Calling SwapIt from within SwapIt is recursive programming.

You must test for an exit condition before you call it from within. Otherwise, you get the equivalent of an infinite loop - except it's now infinite recursion.

And just as you have to make sure that loops advance, you need to make sure each recursion involve some form of advancement, the next whatever, before calling it.

A count down loop

  test ecx,ecx
xloop:
  jz endxloop
  push ecx
  ; ... work code here ...
  pop ecx
  dec ecx  ; advance counter
  jmp xloop
endxloop:


gets transformed to

xrecurse:
  test ecx,ecx
  jz endrecurse
  push ecx
  ; ... work code here ...
  pop ecx
  dec ecx  ; advance counter
  call xrecurse
  ret
endrecurse:


Recursion becomes more useful when dealing with tree structures and tree-like processing, such as walking through a directory tree.
Title: Re: Calling from a proc
Post by: dedndave on October 28, 2011, 03:51:29 PM
 :bg
i know what a recursive call is - and this isn't it

he has no need, nor intention, of using recursion
he is simply shuffling things around a bit, and accidently put the call inside the proc
Title: Re: Calling from a proc
Post by: tenkey on October 28, 2011, 04:04:44 PM
 But there it is - the rules for it :green2
Title: Re: Calling from a proc
Post by: bcddd214 on November 03, 2011, 11:04:25 PM
In this format the programs is up to specs from what I understand except for the flip action is disabled.
In this format the registers are protected and it reads and counts the number of string.
The only thing to do at this point is implement the flip proc from StringLength or uncommenting line 41.

But she hangs if I do?

****************************
        TITLE   FlipTest
        INCLUDE Irvine32.inc

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

        .DATA

Mes1    BYTE "Enter a 5 digit string: ",0
InName  BYTE 6 dup(0)

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

        .CODE

;************************************************

GetInput PROC

        push    edx
        mov     edx, eax
        call    WriteString
        pop     edx
        call    ReadString
        ret

GetInput ENDP

;************************************************

StringLength PROC
      push    ebp
      mov      ebp, esp
        push    edi
        mov     al, 0
        or      ecx, -1
        mov     edi, [ebp+8]
        repnz   scasb
        neg     ecx
        sub     ecx, 2
      mov      eax, ecx
;      call   SwapIt
        pop     edi
      pop      ebp
        ret   4

StringLength ENDP

;************************************************

SwapIt  PROC
        push    ebp
      mov     ebp, esp
        push    eax
        push    ecx
        push    edx      
      push    [ebp + 8]
;      call    StringLength
      mov      ecx, eax
        dec     ecx      
        add     ecx, edx
        jmp short SwpIt1

SwpIt0: mov     al, [edx]
        mov     ah, [ecx]
        mov     [ecx], al
        mov     [edx], ah
        dec     ecx
        inc     edx

SwpIt1: cmp     ecx, edx
        ja      SwpIt0

        pop     edx
        pop     ecx
        pop     eax
      pop     ebp
        ret

SwapIt  ENDP

;************************************************

Main    PROC

        mov     eax, offset Mes1
        mov     edx, offset InName
        mov     ecx, sizeof InName
        call    GetInput

      push    OFFSET InName
;        call    SwapIt
      call   StringLength
      call   writedec
        call    WriteString
        call    Crlf
        exit

Main    ENDP

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

        END     Main
Title: Re: Calling from a proc
Post by: bcddd214 on November 16, 2011, 12:55:47 AM
?
Title: Re: Calling from a proc
Post by: dedndave on November 16, 2011, 01:55:43 AM
try this - i did not test it   :P
        TITLE   FlipTest

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

        INCLUDE Irvine32.inc

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

GetInput     PROTO :LPSTR, :LPSTR, :UINT
StringLength PROTO :LPSTR
SwapIt       PROTO :LPSTR

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

        .DATA

Mes1    BYTE "Enter a 5 digit string: ", 0
InName  BYTE 6 dup(0)

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

        .CODE

;************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

GetInput PROC   lpszString:LPSTR, lpBuffer:LPSTR, uLength:UINT

;Call With: lpszString = pointer to message string
;             lpBuffer = pointer to input buffer
;              uLength = length of input buffer
;
;  Returns: buffer is filled with user input
;           ECX, EDX are destroyed

        push    epb
        mov     ebp, esp
        mov     edx, [ebp+8]          ;lpszString
        call    WriteString
        mov     edx, [ebp+12]         ;lpBuffer
        mov     ecx, [ebp+16]         ;uLength
        call    ReadString
        pop     ebp
        ret     12                    ;return and discard 3 dwords

GetInput ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

StringLength PROC lpszString:LPSTR

;Call With: lpszString = pointer to null-terminated string
;
;  Returns: EAX = string length
;           ECX is destroyed

        push    edi
        push    ebp
        mov     ebp, esp
        mov     al, 0
        or      ecx, -1
        mov     edi, [ebp+12]         ;lpszString
        repnz   scasb
        or      eax, -2
        sub     eax, ecx
        pop     ebp
        pop     edi
        ret     4                     ;return and discard 1 dword

StringLength ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

SwapIt  PROC    lpszString:LPSTR

;Call With: lpszString = pointer to null-terminated string
;
;  Returns: string is reversed
;           EDX = pointer to reversed string
;           EAX, ECX are destroyed

        push    ebp
        mov     ebp, esp
        INVOKE  StringLength, [ebp+8]
        mov     edx, [ebp+8]          ;lpszString
        dec     eax
        push    edx
        add     eax, edx
        jmp short SwpIt1

SwpIt0: mov     cl, [edx]
        mov     ch, [eax]
        mov     [eax], cl
        mov     [edx], ch
        dec     eax
        inc     edx

SwpIt1: cmp     eax, edx
        ja      SwpIt0

        pop     edx
        pop     ebp
        ret     4                     ;return and discard 1 dword

SwapIt  ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;************************************************

Main    PROC

        INVOKE  GetInput, offset Mes1, offset InName, sizeof InName
        INVOKE  SwapIt, offset InName
        call    WriteString
        call    Crlf
        exit

Main    ENDP

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

        END     Main
Title: Re: Calling from a proc
Post by: dedndave on November 16, 2011, 01:58:40 AM
the assembler will generate the same code as though you had written Main like this
;************************************************

Main    PROC

        push    sizeof InName
        push    offset InName
        push    offset Mes1
        call    GetInput
        push    offset InName
        call    SwapIt
        call    WriteString
        call    Crlf
        exit

Main    ENDP

;################################################
Title: Re: Calling from a proc
Post by: bcddd214 on November 26, 2011, 05:14:46 PM
Here is the compile output.

Assembling: flipTest4.asm
flipTest4.asm(9) : error A2006: undefined symbol : LPSTR
flipTest4.asm(9) : error A2195: parameter or local cannot have void type
flipTest4.asm(9) : error A2129: VARARG parameter must be last parameter
flipTest4.asm(9) : error A2006: undefined symbol : UINT
flipTest4.asm(9) : error A2131: VARARG parameter requires C calling convention
flipTest4.asm(10) : error A2006: undefined symbol : LPSTR
flipTest4.asm(10) : error A2195: parameter or local cannot have void type
flipTest4.asm(10) : error A2131: VARARG parameter requires C calling convention
flipTest4.asm(11) : error A2006: undefined symbol : LPSTR
flipTest4.asm(11) : error A2195: parameter or local cannot have void type
flipTest4.asm(11) : error A2131: VARARG parameter requires C calling convention
flipTest4.asm(29) : error A2006: undefined symbol : LPSTR
flipTest4.asm(29) : error A2195: parameter or local cannot have void type
flipTest4.asm(29) : error A2111: conflicting parameter definition
flipTest4.asm(58) : error A2005: symbol redefinition : lpszString
flipTest4.asm(58) : error A2111: conflicting parameter definition
flipTest4.asm(88) : error A2005: symbol redefinition : lpszString
flipTest4.asm(88) : error A2111: conflicting parameter definition
flipTest4.asm(128) : error A2114: INVOKE argument type mismatch : argument : 2
flipTest4.asm(128) : error A2114: INVOKE argument type mismatch : argument : 1
flipTest4.asm(129) : error A2114: INVOKE argument type mismatch : argument : 1
flipTest4.asm(38) : error A2006: undefined symbol : epb
Press any key to continue . . .
Title: Re: Calling from a proc
Post by: bcddd214 on November 26, 2011, 06:25:32 PM
I would love a response to this post. I really have things broken down in a manner I can understand them (at this point). Your later posting are probably correct but my brain will be able to comfortably twist to your side of the force once I understand where I am at here.
at line 41, I have disabled swapit. I am trying find out if I am where I need to be at this point before trying to figure out 'why' my handoff to swapit is jacked.  :)

Quote from: bcddd214 on November 03, 2011, 11:04:25 PM
In this format the programs is up to specs from what I understand except for the flip action is disabled.
In this format the registers are protected and it reads and counts the number of string.
The only thing to do at this point is implement the flip proc from StringLength or uncommenting line 41.

But she hangs if I do?

****************************
        TITLE   FlipTest
        INCLUDE Irvine32.inc

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

        .DATA

Mes1    BYTE "Enter a 5 digit string: ",0
InName  BYTE 6 dup(0)

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

        .CODE

;************************************************

GetInput PROC

        push    edx
        mov     edx, eax
        call    WriteString
        pop     edx
        call    ReadString
        ret

GetInput ENDP

;************************************************

StringLength PROC
      push    ebp
      mov      ebp, esp
        push    edi
        mov     al, 0
        or      ecx, -1
        mov     edi, [ebp+8]
        repnz   scasb
        neg     ecx
        sub     ecx, 2
      mov      eax, ecx
;      call   SwapIt
        pop     edi
      pop      ebp
        ret   4

StringLength ENDP

;************************************************

SwapIt  PROC
        push    ebp
      mov     ebp, esp
        push    eax
        push    ecx
        push    edx      
      push    [ebp + 8]
;      call    StringLength
      mov      ecx, eax
        dec     ecx      
        add     ecx, edx
        jmp short SwpIt1

SwpIt0: mov     al, [edx]
        mov     ah, [ecx]
        mov     [ecx], al
        mov     [edx], ah
        dec     ecx
        inc     edx

SwpIt1: cmp     ecx, edx
        ja      SwpIt0

        pop     edx
        pop     ecx
        pop     eax
      pop     ebp
        ret

SwapIt  ENDP

;************************************************

Main    PROC

        mov     eax, offset Mes1
        mov     edx, offset InName
        mov     ecx, sizeof InName
        call    GetInput

      push    OFFSET InName
;        call    SwapIt
      call   StringLength
      call   writedec
        call    WriteString
        call    Crlf
        exit

Main    ENDP

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

        END     Main
Title: Re: Calling from a proc
Post by: jj2007 on November 26, 2011, 07:36:00 PM
Hi,
I don't have the Irvine package but managed to "emulate" it partially. Here is what I found...

QuoteSwapIt PROC
   push ebp
   mov ebp, esp
   push eax
   push ecx
   push edx
   push [ebp + 8]
   push edx
;   call StringLength   ; calls SwapIt, not possible
   mov eax, len(eax)   ; Masm32 substitute
   pop edx
   mov ecx, eax
   dec ecx
   add ecx, edx
   jmp short SwpIt1

SwpIt0:   mov al, [edx]
   mov ah, [ecx]
   mov [ecx], al
   mov [edx], ah
   dec ecx
   inc edx

SwpIt1:   cmp ecx, edx
   ja SwpIt0
   pop edx   ; YOUR STACK IS NOT BALANCED
   pop edx
   pop ecx
   pop eax
   pop ebp
   ret
SwapIt ENDP
Title: Re: Calling from a proc
Post by: dedndave on November 26, 2011, 07:38:17 PM
ok - let's try this again.....
        TITLE   FlipTest

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

        INCLUDE Irvine32.inc

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

GetInput     PROTO :DWORD, :DWORD, :DWORD
StringLength PROTO :DWORD
SwapIt       PROTO :DWORD

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

        .DATA

Mes1    BYTE "Enter a 5 digit string: ", 0
InName  BYTE 6 dup(0)

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

        .CODE

;************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

GetInput PROC   lpszString:DWORD, lpBuffer:DWORD, uLength:DWORD

;Call With: lpszString = pointer to message string
;             lpBuffer = pointer to input buffer
;              uLength = length of input buffer
;
;  Returns: buffer is filled with user input
;           ECX, EDX are destroyed

        push    ebp
        mov     ebp, esp
        mov     edx, [ebp+8]          ;lpszString
        call    WriteString
        mov     edx, [ebp+12]         ;lpBuffer
        mov     ecx, [ebp+16]         ;uLength
        call    ReadString
        pop     ebp
        ret     12                    ;return and discard 3 dwords

GetInput ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

StringLength PROC lpszString:DWORD

;Call With: lpszString = pointer to null-terminated string
;
;  Returns: EAX = string length
;           ECX is destroyed

        push    edi
        push    ebp
        mov     ebp, esp
        mov     al, 0
        or      ecx, -1
        mov     edi, [ebp+12]         ;lpszString
        repnz   scasb
        or      eax, -2
        sub     eax, ecx
        pop     ebp
        pop     edi
        ret     4                     ;return and discard 1 dword

StringLength ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

SwapIt  PROC    lpszString:DWORD

;Call With: lpszString = pointer to null-terminated string
;
;  Returns: string is reversed
;           EDX = pointer to reversed string
;           EAX, ECX are destroyed

        push    ebp
        mov     ebp, esp
        INVOKE  StringLength, [ebp+8]
        mov     edx, [ebp+8]          ;lpszString
        dec     eax
        push    edx
        add     eax, edx
        jmp short SwpIt1

SwpIt0: mov     cl, [edx]
        mov     ch, [eax]
        mov     [eax], cl
        mov     [edx], ch
        dec     eax
        inc     edx

SwpIt1: cmp     eax, edx
        ja      SwpIt0

        pop     edx
        pop     ebp
        ret     4                     ;return and discard 1 dword

SwapIt  ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;************************************************

Main    PROC

        INVOKE  GetInput, offset Mes1, offset InName, sizeof InName
        INVOKE  SwapIt, offset InName
        call    WriteString
        call    Crlf
        exit

Main    ENDP

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

        END     Main
Title: Re: Calling from a proc
Post by: bcddd214 on November 26, 2011, 07:51:41 PM
Thank you for your reply!
#1  Why is it not possible to call on stinglength from swap it? I think you are hitting on a note that a colleague purposely put me into this trap in order to get and understanding of while we push a pop at the beginning to force the proper passing of safe data through bp. I might be wrong for a reason and would enjoy knowing why.

#2 Stack not balanced? Can you explain my friend?

Quote from: jj2007 on November 26, 2011, 07:36:00 PM
Hi,
I don't have the Irvine package but managed to "emulate" it partially. Here is what I found...

QuoteSwapIt PROC
   push ebp
   mov ebp, esp
   push eax
   push ecx
   push edx
   push [ebp + 8]
   push edx
;   call StringLength   ; calls SwapIt, not possible
   mov eax, len(eax)   ; Masm32 substitute
   pop edx
   mov ecx, eax
   dec ecx
   add ecx, edx
   jmp short SwpIt1

SwpIt0:   mov al, [edx]
   mov ah, [ecx]
   mov [ecx], al
   mov [edx], ah
   dec ecx
   inc edx

SwpIt1:   cmp ecx, edx
   ja SwpIt0
   pop edx   ; YOUR STACK IS NOT BALANCED
   pop edx
   pop ecx
   pop eax
   pop ebp
   ret
SwapIt ENDP
Title: Re: Calling from a proc
Post by: jj2007 on November 26, 2011, 08:01:38 PM
#1  Why is it not possible to call on stinglength from swap it?
Because you would enter an endless loop: a calls b calls a calls b calls a calls....

#2 Stack not balanced? Can you explain my friend?
You are pushing more than you pop. As a result, the return address is not where the ret expects it, and your ret ends up in no man's land.

You should consider using a debugger, e.g. OllyDbg (http://www.ollydbg.de/version2.html). It helps a lot to see where the crash happens...
Title: Re: Calling from a proc
Post by: bcddd214 on November 26, 2011, 10:54:53 PM
My logic should be fixed but she still hangs.
line 59 which commented now for debugging but should have fixed my balance error when implemented does not.


        TITLE   FlipTest
        INCLUDE Irvine32.inc

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

        .DATA

Mes1    BYTE "Enter a 5 digit string: ",0
InName  BYTE 6 dup(0)

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

        .CODE

;************************************************

GetInput PROC

        push    edx
        mov     edx, eax
        call    WriteString
        pop     edx
        call    ReadString
        ret

GetInput ENDP

;************************************************

StringLength PROC
      push    ebp
      mov      ebp, esp
        push    edi
        mov     al, 0
        or      ecx, -1
        mov     edi, [ebp+8]
        repnz   scasb
        neg     ecx
        sub     ecx, 2
      mov      eax, ecx
;      call   SwapIt
        pop     edi
      pop      ebp
        ret   4

StringLength ENDP

;************************************************

SwapIt  PROC
        push    ebp
      mov     ebp, esp
        push    eax
        push    ecx
        push    edx      
      push    [ebp + 8]
;      call    StringLength
; new
;      pop edx
      mov      ecx, eax
        dec     ecx      
        add     ecx, edx
        jmp short SwpIt1

SwpIt0: mov     al, [edx]
        mov     ah, [ecx]
        mov     [ecx], al
        mov     [edx], ah
        dec     ecx
        inc     edx

SwpIt1: cmp     ecx, edx
        ja      SwpIt0

        pop     edx
        pop     ecx
        pop     eax
      pop     ebp
        ret

SwapIt  ENDP

;************************************************

Main    PROC

        mov     eax, offset Mes1
        mov     edx, offset InName
        mov     ecx, sizeof InName
        call    GetInput

      push    OFFSET InName
      call   StringLength
        call    SwapIt
      call   writedec
        call    WriteString
        call    Crlf
        exit

Main    ENDP

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

        END     Main
Title: Re: Calling from a proc
Post by: bcddd214 on November 26, 2011, 11:30:53 PM
This is brilliant. I am just breaking her down now.
What is "OPTION  PROLOGUE:PrologueDef"?


Quote from: bcddd214 on November 26, 2011, 07:51:41 PM
Thank you for your reply!
#1  Why is it not possible to call on stinglength from swap it? I think you are hitting on a note that a colleague purposely put me into this trap in order to get and understanding of while we push a pop at the beginning to force the proper passing of safe data through bp. I might be wrong for a reason and would enjoy knowing why.

#2 Stack not balanced? Can you explain my friend?

Quote from: jj2007 on November 26, 2011, 07:36:00 PM
Hi,
I don't have the Irvine package but managed to "emulate" it partially. Here is what I found...

QuoteSwapIt PROC
   push ebp
   mov ebp, esp
   push eax
   push ecx
   push edx
   push [ebp + 8]
   push edx
;   call StringLength   ; calls SwapIt, not possible
   mov eax, len(eax)   ; Masm32 substitute
   pop edx
   mov ecx, eax
   dec ecx
   add ecx, edx
   jmp short SwpIt1

SwpIt0:   mov al, [edx]
   mov ah, [ecx]
   mov [ecx], al
   mov [edx], ah
   dec ecx
   inc edx

SwpIt1:   cmp ecx, edx
   ja SwpIt0
   pop edx   ; YOUR STACK IS NOT BALANCED
   pop edx
   pop ecx
   pop eax
   pop ebp
   ret
SwapIt ENDP
Title: Re: Calling from a proc
Post by: bcddd214 on November 26, 2011, 11:35:25 PM
I don't think 'or' is a directive is it?
one of the tricks to this is I can't use any directives like 'if'.

Quote from: dedndave on November 26, 2011, 07:38:17 PM
ok - let's try this again.....
        TITLE   FlipTest

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

        INCLUDE Irvine32.inc

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

GetInput     PROTO :DWORD, :DWORD, :DWORD
StringLength PROTO :DWORD
SwapIt       PROTO :DWORD

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

        .DATA

Mes1    BYTE "Enter a 5 digit string: ", 0
InName  BYTE 6 dup(0)

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

        .CODE

;************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

GetInput PROC   lpszString:DWORD, lpBuffer:DWORD, uLength:DWORD

;Call With: lpszString = pointer to message string
;             lpBuffer = pointer to input buffer
;              uLength = length of input buffer
;
;  Returns: buffer is filled with user input
;           ECX, EDX are destroyed

        push    ebp
        mov     ebp, esp
        mov     edx, [ebp+8]          ;lpszString
        call    WriteString
        mov     edx, [ebp+12]         ;lpBuffer
        mov     ecx, [ebp+16]         ;uLength
        call    ReadString
        pop     ebp
        ret     12                    ;return and discard 3 dwords

GetInput ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

StringLength PROC lpszString:DWORD

;Call With: lpszString = pointer to null-terminated string
;
;  Returns: EAX = string length
;           ECX is destroyed

        push    edi
        push    ebp
        mov     ebp, esp
        mov     al, 0
        or      ecx, -1
        mov     edi, [ebp+12]         ;lpszString
        repnz   scasb
        or      eax, -2
        sub     eax, ecx
        pop     ebp
        pop     edi
        ret     4                     ;return and discard 1 dword

StringLength ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

SwapIt  PROC    lpszString:DWORD

;Call With: lpszString = pointer to null-terminated string
;
;  Returns: string is reversed
;           EDX = pointer to reversed string
;           EAX, ECX are destroyed

        push    ebp
        mov     ebp, esp
        INVOKE  StringLength, [ebp+8]
        mov     edx, [ebp+8]          ;lpszString
        dec     eax
        push    edx
        add     eax, edx
        jmp short SwpIt1

SwpIt0: mov     cl, [edx]
        mov     ch, [eax]
        mov     [eax], cl
        mov     [edx], ch
        dec     eax
        inc     edx

SwpIt1: cmp     eax, edx
        ja      SwpIt0

        pop     edx
        pop     ebp
        ret     4                     ;return and discard 1 dword

SwapIt  ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;************************************************

Main    PROC

        INVOKE  GetInput, offset Mes1, offset InName, sizeof InName
        INVOKE  SwapIt, offset InName
        call    WriteString
        call    Crlf
        exit

Main    ENDP

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

        END     Main

Title: Re: Calling from a proc
Post by: jj2007 on November 26, 2011, 11:39:23 PM
Quote from: bcddd214 on November 26, 2011, 11:30:53 PM
This is brilliant. I am just breaking her down now.
What is "OPTION  PROLOGUE:PrologueDef"?

It means "insert a stack frame if needed" and is the default mode, so you don't have to specify it. You are doing it "by hand" with the push ebp/pop ebp sequence, by the way: without any need and without any effect. You will have to take that off, and use the none directives instead of the Def ones, in combination with retn 4.
My advice: RTFM (http://www.urbandictionary.com/define.php?term=RTFM).
Title: Re: Calling from a proc
Post by: dedndave on November 26, 2011, 11:45:02 PM
i don't think you can write much of a program without using directives
TITLE, INCLUDE, PROTO, .DATA, BYTE, .CODE, OPTION, PROC, ENDP, and END are all directives
others are necessary that are in Irvine32.inc, like .MODEL

perhaps what is meant is "you can't use any conditional directives", like IF

the OPTION Prologue and OPTION Epilogue directives are used to control the way the assembler creates PROCS

if there are any parameters on the PROC line, or if there are any local variables, the assembler generates
a prologue at the beginning of the PROC and an epilogue anywhere a RET appears

we want to write our own so that we can see PUSH EBP, POP EBP, etc in our code
if we do not turn them off with OPTION, the assembler generates code we do not see in the source

OR is an instruction - not a directive
        or      eax, -2

OR can also be an operator, but not in that case
here, we see it used as an operator
SOME_CONSTANT EQU 6 or 14
Title: Re: Calling from a proc
Post by: dedndave on November 26, 2011, 11:54:44 PM
the way OR is used in the StringLength PROC, it could be replaced with MOV
        mov     ecx, -1
        mov     edi, [ebp+12]         ;lpszString
        repnz   scasb
        mov     eax, -2


by using OR, it saves 2 bytes in each case
Title: Re: Calling from a proc
Post by: bcddd214 on November 27, 2011, 12:41:40 AM
already read the manual, this is the practical app after.
If it's all the same and possible, I rather do both just to tick a third party whom is breathing down my next for gross overkill.
I know I am doing both and I only need one but I also know why both are there and it is in the interest of gross overkill.

Quote from: jj2007 on November 26, 2011, 11:39:23 PM
Quote from: bcddd214 on November 26, 2011, 11:30:53 PM
This is brilliant. I am just breaking her down now.
What is "OPTION  PROLOGUE:PrologueDef"?

It means "insert a stack frame if needed" and is the default mode, so you don't have to specify it. You are doing it "by hand" with the push ebp/pop ebp sequence, by the way: without any need and without any effect. You will have to take that off, and use the none directives instead of the Def ones, in combination with retn 4.
My advice: RTFM (http://www.urbandictionary.com/define.php?term=RTFM).
Title: Re: Calling from a proc
Post by: dedndave on November 27, 2011, 12:19:42 PM
one way to learn about stack frames (EBP, prologues, epilogues) is to look at a few routines written both ways
a while back, i made a couple posts on this subject.....

http://www.masm32.com/board/index.php?topic=15307.msg124847#msg124847

http://www.masm32.com/board/index.php?topic=14381.msg114921#msg114921

you can also read the documentation in the MASM reference manual....

http://www.4shared.com/file/39MdNf_v/MASMProgGuide.html