;***************************************************************************** ; This program is designed to show how to pass parameters via a "stack frame". ; It also illustrates how the stack is used when pushad, pushfd, popfd, and ; popad are used within a procedure. One must remember that passed data items ; are underneath 36 bytes of stored registers. ; ; Written by Joe Toone 10/17/2006 2:10:50 PM ;***************************************************************************** TITLE stackfrm.asm ;file name of program LF equ 0ah ;ASCII 10 - newline character CR equ 0dh ;ASCII 13 - carriage return character MAXSTR equ 256d ;256 bytes maximum string length .586 ;Allow for Pentium instrucitons .MODEL FLAT ;Memory model is FLAT (4GB) include io32.inc ;Include I/O procdures .STACK 4096h ;4k hex bytes for stack .DATA ;Data segment begins here Intro BYTE LF,LF,CR,'This program finds the Greatest Common Divisor ' BYTE 'of two numbers',CR,LF,'entered by the user.',CR,LF,LF BYTE 'Enter the first number or [Enter] to quit --> ',0 SecondNum BYTE CR,LF,'Enter the second number --> ',0 GCDis BYTE CR,LF,'The GCD is --> ',0 AsciiNum1 BYTE 16d dup(0) AsciiNum2 BYTE 16d dup(0) AsciiAnswer BYTE 16d dup(0) Number1 DWORD 0h Number2 DWORD 0h Answer DWORD 0h ;************************** Main Body of Program ***************************** ; Given : Nothing ; Process: Main Body - calls procedures to do the processing and passes ; parameters on the stack. ; Return : Zero (0) ;***************************************************************************** .CODE ;executable section begins here _main: lea esi,Intro ;point to the question prompt call PrintString ;go print the string lea esi,AsciiNum1 ;pointer to string buffer in data call GetString ; get the string cmp AsciiNum1,0h ;is the string empty jz ByeBye ; yes, then exit lea esi,SecondNum ;point to second input prompt call PrintString ; and print the prompt lea esi,AsciiNum2 ;pointer to string buffer in data call GetString ; get the string lea esi,AsciiNum1 ;point to first ascii number lea edi,Number1 ;point to first integer storage call Ascii2Int ; convert first number to integer lea esi,AsciiNum2 ;point to first ascii number lea edi,Number2 ;point to first integer storage call Ascii2Int ; convert first number to integer push Number1 ;push the first parameter on stack push Number2 ;push the second parameter on stack call FindGCD ;go find the greatest common divisor pop Answer ;retrieve the answer from the stack lea esi,Answer ;point to the answer lea edi,AsciiAnswer ;point to the ascii version of answer call Int2Ascii ; go convert int to ascii lea esi,GCDis ;point to answer statement call PrintString ; and print it lea esi,AsciiAnswer ;point to answer call PrintString ; and print it NextMenu:jmp _main ;go back to the intro question ByeBye: INVOKE ExitProcess, 0 ; exit with return code 0 ;************************ Procedure Output the Result ************************* ; Given : Two dword numbers on the stack ; Process : Find the Greatest Common Divisor for the two numbers using the ; stack for local variable space. All registers are preserved and ; the stack pointers ESP and EBP will be pointing to their original ; locations after returning from the procedure. ; Return : The answer as the top item on the stack. It must then be stored ; in a global dword memory variable or register using "pop" ;****************************************************************************** FindGCD PROC NEAR32 pushad ;Saves eax,ecx,edx,ebx,esp,ebp,esi,edi ; in that order (32 bytes) on stack top pushfd ;Saves eflags (4 bytes) on stack top ;We now have burried our parameters ; by a total of 36 bytes in order to ; protect all registers. ;Establish a stack frame push ebp ;Save current stack base pointer mov ebp,esp ; set base pointer equal to top sub esp,4d ;Allocate one dword of storage for GCD mov eax,[ebp+44] ;set eax = Number1 mov [ebp-4],eax ;set GCD = Number1 mov edx,[ebp+48] ;set Remainder = Number2 Remainder: mov eax,[ebp-4] ;set Dividend = GCD mov [ebp-4],edx ;set GCD = Remainder mov edx,0 ;set Remainder = 0 div DWORD PTR [ebp-4] ;Divide, leaving Remainder in edx cmp edx,0 ;Is the Remainder = 0? jnz Remainder ; no, then divide again mov eax,[ebp-4] ; yes, store the answer mov [ebp+48],eax ;Overwrite the first paramter passed ; with the final answer mov esp,ebp ;Remove the stack frame pop ebp ; recover the base pointer popfd ;Restore the registers popad ; ret 4 ;Discard the second parameter passed FindGCD ENDP ; Return to Calling procedure ;The answer is now on top of the stack Public _main END ;Code segment ends