News:

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

Calling from a proc

Started by bcddd214, October 25, 2011, 08:09:52 PM

Previous topic - Next topic

bcddd214

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

jj2007

Why do you believe that the assembler should understand call SwapIt offset inName,eax ?

dedndave

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

bcddd214

But SwapIt cannot occur in main. It has to be called from the 'StringLength PROC'???

bcddd214

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

dedndave

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

bcddd214

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

dedndave

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

tenkey

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.
A programming language is low level when its programs require attention to the irrelevant.
Alan Perlis, Epigram #8

dedndave

 :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

tenkey

 But there it is - the rules for it :green2
A programming language is low level when its programs require attention to the irrelevant.
Alan Perlis, Epigram #8

bcddd214

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


dedndave

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

dedndave

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

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