* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
AGENDA Runtime stack. Procedures Procedures Definition Procedures Call Sum Integer Array Example CALL and RET Instructions Passing Parameters to Procedures Using Registers Sum Integer Array Example (Using Registers) Using Stack (Manually) Using Stack and Invoke Directive Defining Procedures Declaration, Definition, and Call Sum Integer Array Example (Using Stack) Hands On 2 RUNTIME STACK WHAT IS RUNTIME STACK? Same as stack : FILO (First In Last Out) / LIFO Temporary array (segment) in the memory managed by the CPU. It’s managed using SS & ESP registers 4 EXAMPLE Stack Push x Push y Pop Push z ESP X 1000 Y Z FFC FF8 5 WHY USE STACK? Saving register values temporarily Saving the return address of the called procedures Passing parameters to procedures Local variables defined in a procedure are created in its beginning and destroyed in its end. 6 STACK INSTRUCTIONS PUSH r/m16 | r/m32 | imm32 POP r/m16 | r/m32 PUSHAD in the following order : EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI POPAD EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX) 7 PUSHFD/POPFD Procedures • As we know, we should not write the whole program in a single chunk. • Program code should be divided into pieces, each piece performs specific function, takes specific input, and produces specific output. • We often called these pieces as functions or procedures, but it still has the same meaning. 9 Procedures Definition • To define a procedure, use PROC and ENDP directives to encapsulate procedure code. • For example, the following is the definition of a function called Sample1: Sample1 PROC … RET Sample1 ENDP 10 Procedures Call • To call a procedure, use CALL instruction, as follows: CALL Sample1 11 Sum Integer Array Example INCLUDE Irvine32.inc .data Arr1 DWORD 10,20,30,40,50 .code main PROC ; main procedure begin call SumArr ; call SumArr procedure call writeint ; output the sum (which already stored in EAX) call CrLf exit main ENDP ;main procedure end SumArr PROC ; SumArr procedure begins mov esi, offset Arr1 ;put array address in esi mov eax, 0 ;initialize eax by zero for sum mov ecx, LENGTHOF Arr1 ;initialize ecx by array size sum_loop: add eax, DWORD PTR [esi] add esi, 4 ; increment esi pointer by the size of the array element loop sum_loop RET ;Return to the main procedure12 SumArr ENDP ; end of procedure END main Sum Integer Array Example • As we write procedural code, we make the main program code itself in a procedure called main (however, it can take any other name). 13 Sum Integer Array Example • The main procedure does not require a RET instruction at its end, as it is ended by exit which terminates the whole program and returns to Windows OS. (exit is an alias for ExitProcess Windows API function). • In contrast, the SumArr must ended by RET instruction to allow return to the main program. • If it is missed, the program continues execution to next machine code which it does not correspond to a valid machine instruction and causing a program crash. 14 Sum Integer Array Example • The SumArr procedure calculates the summation in EAX register and implicitly returns this value to the main program in EAX itself. • Returning values in registers is possible as the registers values do not change when returning from a procedure. 15 CALL and RET Instructions • CPU knows the next instruction by storing its address in EIP (Instruction Pointer) register. • So, at any time during the program run, EIP contains the address of next instruction to be executed. • Therefore, to change the program flow by a jump or CALL instructions, CPU updates the EIP value to be the address of the jumped instruction or the address of the called procedure. 17 CALL and RET Instructions • A trivial question popped in mind, how RET instruction knows the correct address to return to after a procedure end? • This can be accomplished by saving the return address which is the address of the next instruction after CALL instruction. • Well, good answer, but where to save it? • The most suitable place to save the return address is the stack. Therefore, return address is pushed by CALL instruction and popped by RET instruction. 18 CALL and RET Instructions Address 00000020 00000025 00000040 Code main PROC call MySub mov eax, ebx … main ENDP MySub PROC mov eax, edx … RET MySub ENDP 19 Passing Parameters to Procedures • Using Registers. • Using Stack (Manually). • Using Stack and Invoke Directive. 21 Sum Integer Array Example INCLUDE Irvine32.inc .data Arr1 DWORD 10,20,30,40,50 .code main PROC ; main procedure begin call SumArr ; call SumArr procedure call writeint ; output the sum (which already stored in EAX) call CrLf exit main ENDP ;main procedure end SumArr PROC ; SumArr procedure begins mov esi, offset Arr1 ;put array address in esi mov eax, 0 ;initialize eax by zero for sum mov ecx, LENGTHOF Arr1 ;initialize ecx by array size sum_loop: add eax, DWORD PTR [esi] add esi, 4 ; increment esi pointer by the size of the array element loop sum_loop RET ;Return to the main procedure22 SumArr ENDP ; end of procedure END main Passing Parameters to Procedures Using Registers • In the example of summing the integer array elements, we saw how to sum integer arrays by a separate procedure from the main program. • But it has a problem, it runs only on fixed array (i.e. Arr1) with fixed length, and so this procedure cannot be reused with any other array. • So, we need to pass the array address and its length to the procedure to be able to run on different 23 arrays with different lengths. Passing Parameters to Procedures Using Registers • We can use general‐purpose registers to pass parameters to procedures. • As performed when calling WriteInt, or WriteString procedures that are defined in Irvine library. • They receive parameters in EAX and EDX registers respectively. 24 Passing Parameters to Procedures Using Registers • The following example calculates the sum of an integer array using a procedure which takes the address of the array in ESI register and its length in ECX register. 25 Sum Integer Array Example (Using Registers) INCLUDE Irvine32.inc .data arr1 DWORD 10,20,30,40,50 .code main PROC ;main procedure begin mov esi, offset arr1 ;pass array address in esi as a parameter mov ecx, LENGTHOF arr1 ;pass array length in ecx as a parameter call SumArr ;call SumArr procedure to sum array call writeint ;output the summation exit main ENDP ;main procedure end SumArr PROC procedure begins ;save the esi and ecx values from changes happened inside this procedure push esi push ecx mov eax, 0 sum_loop: add eax, DWORD PTR [esi] add esi, 4 ;increment esi pointer by 4 loop sum_loop pop ecx ;restore ecx value from stack pop esi ;restore esi value from stack Ret ;Return execution to the main procedure 26 SumArr ENDP ;SumArr procedure end END main Sum Integer Array Example (Using Registers) • SumArr procedure now uses ESI and ECX registers as the array address and the array length respectively, so it can be used with any integer array of any length. • As SumArr modifies the ESI and ECX registers: • First, it pushes them in the stack to temporarily save them. • At the end, it pops the stack to restore their values. 27 Passing Parameters to Procedures Using Stack (Manually) • Passing parameters using registers is limited according to the limited number of registers. • Therefore, there is a more efficient way to pass parameters to procedures which pushes parameters into runtime stack while the called procedure pops them to work on. 28 Passing Parameters to Procedures Using Stack and INVOKE Directive • MASM provides an easy way to pass parameters in the stack, by allowing PROC directive to accept a list of parameters. • In addition, INVOKE directive can be used to call procedures with a list of arguments instead of CALL instruction. • You can do the job of passing parameters in the stack manually without using INVOKE directive, but using the INVOKE directive will simplify the operation because it is much like calling functions in high‐level 29 languages. Defining Procedures with Parameters <Label> … … RET <Label> PROC paramName: type, ..., paramName: type • paramName is an arbitrary name you assign to the parameter. • type is the type of the parameter. It can be one of the following: • One of the known types (BYTE, WORD, DWORD, …). • Pointer to one of the above types, to handle calling by reference. • To specify a pointer, use PTR specifier before the type 30 as follows, PTR BYTE, PTR WORD, etc. Calling Procedures with Stack Parameters INVOKE procedureName [, argumentList] • argumentList is a comma‐separated list of arguments to be passed to the procedure named procedureName. • INVOKE directive allows calling procedures defined with stack parameters while CALL instruction doesn’t. 31 Declaring Procedures • A procedure must be defined before calling it by INVOKE directive. • Otherwise, assembler gives undefined symbol error. • Therefore, we use PROTO directive to declare this procedure, and put the definition anywhere in the code. 32 Declaring Procedures <Label> PROTO paramName: type, ..., paramName: type • PROTO directive allows declaring the prototype of a specific procedure. • Procedure prototype can be placed in any location before invoke statement, even inside main procedure. • Note that the label declared in PROTO must match the 33 label specified in PROC directive. Procedures Declaration, Calling, and Definition <Label> PROTO paramName: type, ..., paramName: type INVOKE procedureName , argument1, argument2, .. <Label> <Label> PROC … … RET paramName: type, ..., paramName: type 34 Sum Integer Array Example (Using Stack) INCLUDE Irvine32.inc .data arr1 DWORD 10, 20, 30, 40, 50 .code ; Specify SumArr procedure prototype SumArr PROTO x:PTR DWORD, sz: DWORD main PROC ;use invoke directive to call SumArr procedure and to specify arguments INVOKE SumArr, offset arr1, lengthof arr1 call writeint exit main ENDP ;Specify SumArr procedure definition SumArr PROC Addrs: PTR DWORD, sze: DWORD push esi push ecx mov eax, 0 mov esi, Addrs mov ecx, sze sum_loop: add eax, DWORD PTR [esi] add esi, 4 loop sum_loop pop ecx pop esi 35 Ret SumArr ENDP End main 1- String Reverse • Write the code of a procedure that reverses an entered string. 37 String Reverse • ReverseString procedure takes two pointers: one to the input string, while the other to the reversed string. It also takes the size of the string. • The pointer is defined by PTR operator followed by the size that the pointer points to such as PTR BYTE and PTR DWORD, etc. 38 String Reverse • Readstring is an Irvine function that reads a string from a user. • It takes the address of the input buffer in EDX and the maximum number of characters to read in ECX. • It fills the buffer by the input string and set EAX by the size of the input string. 39 String Reverse INCLUDE Irvine32.inc .data MAX_LEN EQU 80 prompt1 byte "Enter a string: ", 0 prompt2 byte "The reversed string: ", 0 strInp byte MAX_LEN + 1 Dup (?) strOut byte MAX_LEN + 1 Dup (?) .code ;the prototype of the ReverseString procedure ReverseString PROTO Src: PTR BYTE, Dest: PTR BYTE, sze:DWORD main PROC mov edx, offset prompt1 call writestring ;to input a string from user, use ReadString ;[IN] EDX: address of the input buffer mov edx, offset strInp ;[IN] ECX: Maximum number of characters to read mov ecx, MAX_LEN call readstring ;[OUT] EAX: size of the input string ;Call ReverseString procedure and pass its parameters INVOKE ReverseString, offset strInp, offset strOut, eax mov edx, offset prompt2 call writestring mov edx, offset strOut call writestring call crlf exit 40 main ENDP String Reverse ReverseString PROC Src:PTR BYTE, Dest:PTR BYTE, sze:DWORD ;save register values in stack push ecx push edi push eax mov ecx, sze mov edi, Src L1: movzx eax, BYTE PTR [edi] ;push the source string in stack push eax inc edi loop L1 mov ecx, sze mov edi, Dest L2: pop eax ;pop the string from stack to the dest string mov [edi], al ;it is reversed inc edi loop L2 mov BYTE PTR [edi], 0 ;terminate the reversed string by a null char pop eax pop edi pop ecx Ret 41 ReverseString ENDP END main 2- Palindrome A palindrome is a string that reads the same backwards as forwards. For example, abcba, 1221, 55555 …etc. Write an assembly program that reads a string and its size and check if it is palindrome or not. 42 Palindrome MaxLength EQU 100 .data strIn BYTE MaxLength+1 Dup (0) ; when Dup 0 no need to inset a null terminating Char strPrompet BYTE "Please enter your string : ",0 strPal BYTE "Your string is palindrome.",0 strNotPal BYTE "Your string is not palindrome.",0 43 .code ; Proc prototype CheckStringIsPalindrome PROTO strPtr : PTR BYTE, strSize : DWORD main PROC MOV EDX, OFFSET strPrompet ;Write the prompet CALL WriteString MOV EDX, OFFSET strIn MOV ECX, MaxLength CALL ReadString ; Proc Call INVOKE CheckStringIsPalindrome ,OFFSET strIn, EAX exit main ENDP Palindrome CheckStringIsPalindrome PROC strPtr : PTR BYTE, strSize : DWORD PUSHAD MOV ESI, strPtr ; points to the start of the string. MOV EDI, strPtr ADD EDI, strSize DEC EDI ; points to the end of the string. .WHILE ESI < EDI 44 MOV AL, BYTE PTR [ESI] .IF AL != BYTE PTR [EDI] MOV EDX, OFFSET strNotPal JMP BreakLoop .ENDIF INC ESI DEC EDI .ENDW MOV EDX, OFFSET strPal BreakLoop: CALL WriteString CALL CRLF POPAD RET CheckStringIsPalindrome ENDP 1- Write an assembly program that calculates the Fibonacci value of the input index from user. Write the Fibonacci procedure twice, once repetitive and another recursive. (The Fibonacci series is 0, 1, 1, 2, 3, 5, 8, 13…). 2- Write an assembly program that computes the characters frequencies of a given string. For example if a string given ‘adbdbbbaadd’, it should print: a=3 b=4 d=4 3- Write an assembly program that validates the number and order of parentheses in a mathematical expression input from user. It should check that the number of right parentheses and left parentheses are equal. Also, it checks every right (closing) parenthesis is preceded by a matching left (opening) 46 parenthesis.