ECE291 Computer Engineering II Lecture 7 Josh Potts University of Illinois at Urbana- Champaign Outline • Program Stack • PUSH & POP instructions • Procedures • Macros • Macros vs procedures Monday, March 14, 2016 ECE291 – Lecture 7 Slide 2 of 31 Stack Key Characteristics • Used to store temporary data during program execution • One point of access - the top of the stack • A stack is always operated as Last-In-First-Out (LIFO) storage, i.e., data are retrieved in the reverse order to which they were stored • Instructions that directly manipulate the stack – PUSH - place element on top of stack – POP remove element from top of stack - Monday, March 14, 2016 ECE291 – Lecture 7 Slide 3 of 31 Stack Implementation in Memory Original SP In Use In Use In Use Direction of increasing memory addresses In Use Stack grows in direction of decreasing memory addresses In Use In Use FREE SS:SP FREE FREE FREE Monday, March 14, 2016 ECE291 – Lecture 7 SS Slide 4 of 31 Stack Implementation in Memory (cont.) • SS - Stack Segment • SP (stack pointer) always points to the top of the stack – SP initially points to top of the stack (high memory address). – SP decreases as data is PUSHed PUSH AX ==> SUB SP, 2 ; MOV [SS:SP], AX – SP increases as data is POPed POP AX ==> MOV AX, [SS:SP] ; ADD SP, 2 • BP (base pointer) can point to any element on the stack Monday, March 14, 2016 ECE291 – Lecture 7 Slide 5 of 31 PUSH Instruction Example To address 12FFF Register Array BX 03800 PUSH BX AX 6AB3 6AB3 CX 6A 037FF B3 037FE DX SP 0800 SS 0300 03000 STACK segment Monday, March 14, 2016 ECE291 – Lecture 7 Slide 6 of 31 POP Instruction Example To address 0FFFF Register Array AX BX POP BX 392F 392F CX 01008 39 01007 2F 01006 DX SP 1006 SS 0000 00000 STACK segment Monday, March 14, 2016 ECE291 – Lecture 7 Slide 7 of 31 PUSH & POP (More I) • PUSH and POP always store or retrieve words of data (never bytes) in the 8086-80286 microprocessor • The 80386/80486 allow words or double words to be transferred to and from the stack • The source of data for PUSH – any internal 16-bit/32-bit register, immediate data, any segment register, or any two bytes of memory data • The POP places data into – internal register, segment register (except CS), or a memory location Monday, March 14, 2016 ECE291 – Lecture 7 Slide 8 of 31 PUSH & POP (More II) • The 80286 and later microprocessors there is also PUSHA and POPA to store and retrieve, respectively the contents of internal register set (AX, CX, DX, BX, SP, BP, SI, and DI) • Stack initialization, example: – assume that the stack segment resides in memory locations 10000h-1FFFFh – the stack segment (SS) is loaded with 1000h – the SP is loaded with 0000h - to start the stack at the top of the 64K (so first push does 0000h – 0002h = FFFEh, storing data in 1FFFEh and 1FFFFh) Monday, March 14, 2016 ECE291 – Lecture 7 Slide 9 of 31 Stack Use • To store – registers – return address information while procedures are executing – local variables that procedures may require • To pass parameters to procedures (i.e. function arguments) Monday, March 14, 2016 ECE291 – Lecture 7 Slide 10 of 31 Temporary Register Storage • Push and Pop registers to preserve their value Example: push ax ; Place AX on the stack push bx ; Place BX on the stack ... < modify contents of Registers AX & BX > ... pop bx ; Restore original value of BX pop ax ; Restore original value of AX Monday, March 14, 2016 ECE291 – Lecture 7 Slide 11 of 31 Store Return Address of a Procedure PrintRec ... <Print value of a record> ... ret At execution time 1. main ... <Calculate Scores> ... CALL PrintRec <Continue Execution HERE> ... CALL DOSXIT Monday, March 14, 2016 2. 3. 4. 5. 6. ECE291 – Lecture 7 Processor encounters the CALL to the procedure pushes the return address (instruction pointer of the next instruction after the CALL) onto the stack jumps to PrintRec label executes the code therein pops the return address off the stack back into the Instruction Pointer (IP) returns to the calling code Slide 12 of 31 Passing Parameters on the Stack • Stack can be used to pass parameter(s) to a procedure • The caller (you, or rather your program) pushes the parameter onto the stack and the called procedure finds the parameter there • When the procedure completes its task, the parameter should be popped from the stack either by the procedure or by the caller. mov ax, String push ax call getStr Monday, March 14, 2016 ;pointer to variable String ;the proc getStr expects the offset address of ;String to be on the stack ECE291 – Lecture 7 Slide 13 of 31 Passing Parameters on the Stack Example ;Use of Procedures when parameters are passed using Stack ;====== Stack =================================================== stkseg stktop segment stack ; *** STACK SEGMENT *** resb ; 64*8 = 512 Bytes of Stack 64*8 ends ;====== Begin Code/Data ========================================= Segment CODE ; *** CODE SEGMENT *** LEN EQU 80 CR EQU 0dh LF EQU 0ah Prompt1 DB "Input a string", 0 Prompt2 DB "Do another? ", 0 String DB (LEN+1) TIMES DB 0 Monday, March 14, 2016 ECE291 – Lecture 7 Slide 14 of 31 Passing Parameters on the Stack Example (cont.) Main ..start push Prompt2 mov ax, stkseg call putStr mov ss, ax mov mov sp, stktop push ax .begin ax, String call getStr push Prompt1 mov bx, String call putStr cmp BYTE [bx], 'y' push String je .Begin call getStr push String mov ax, 4c00h call putStr int 21h Monday, March 14, 2016 ECE291 – Lecture 7 Slide 15 of 31 Passing Parameters on the Stack Example (cont.) ;OFFSET of string to be printed must ;be on the stack and the string must ;be null terminated je .foundEnd ;when found exit mov dl, [bx] int 21h putStr ; print with 21h push bp inc bx mov bp, sp jmp .nextChar .foundEnd: push ax push bx pop push dx pop bx mov bx, [bp + 4] ;expect bx to point to string mov .nextChar: BYTE [bx], 0h for null terminator Monday, March 14, 2016 OFFSET String dx RETURN IP BP pop ax ;check ret 2 OLD BP AX pop bp ah, 2h ; prepare to print a char with 21h cmp ;point to next char BX SP DX Removes passed parameters from the stack ECE291 – Lecture 7 Slide 16 of 31 Passing Parameters on the Stack Example (cont.) ;OFFSET of large enough buffer must je ;have been pushed onto stack mov [bx], al .getEnd ;string will be null terminated ;bx points to storage location getStr inc bx push bp mov bp, sp push ax push bx jmp .getLoop .getEnd: mov BYTE [bx], 0 ;CR is converted in null term pop bx mov bx, [bp + 4] ;base address of storing buffer mov ah, 01h pop ax OFFSET String pop bp RETURN IP ret 2 .getLoop: int 21h cmp al, CR BP OLD BP AX SP BX ;look for CR in al Monday, March 14, 2016 ECE291 – Lecture 7 Slide 17 of 31 Procedures (Overview) • Group of instructions that usually perform a specific task • Reusable section of the software that is stored in memory once, but used as often as necessary • The stack stores the return address whenever a procedure is called during the execution of the program – CALL pushes the address of the following instruction onto the stack – RET removes the address from the stack so the program returns to the instruction following the call My_Procedure_Label My_Far_Procedure_Label RET • PUSH • JUMP • PUSH • PUSH • JUMP POP (CS:) IP IP My_Subroutine Near calls and returns transfer control between procedures in the same code segment Monday, March 14, 2016 CS IP Segment My_Subroutine:Offset My_Subroutine Far calls and returns pass control between different segments ECE291 – Lecture 7 Slide 18 of 31 Procedures (Overview cont.) • Procedures should save and restore registers that are modified in a subroutine. PrintRec push ax push bx push cx push dx push si < Code modifies AX,BX,CX,DX,SI > pop si pop dx pop cx pop bx pop ax ret Monday, March 14, 2016 ECE291 – Lecture 7 Slide 19 of 31 Procedures (Overview) • Parameters to a procedure can be passed in – on the stack – global memory locations – registers – in the code stream – in a parameter block referenced by a pointer Monday, March 14, 2016 ECE291 – Lecture 7 Slide 20 of 31 Passing Parameters in Registers • Example: putsi (put short integer) routine outputs the value in AL as a signed integer putsi push ;saves AH’s values ax cbw ;signed extend AL --> AX call PUTI ;another procedure that actually does the work ;puti expects the value of the ;signed integer in the AX register pop ax ;restore AH ret Monday, March 14, 2016 ECE291 – Lecture 7 Slide 21 of 31 Passing Parameters in the Code Stream MOV Example: .PrintLp: MOV ……… BX, [BP+2] ;load return address into BX AL, [CS:BX] ;get next character ;check for end of the string call MyPrint CMP AL, 0 DB “Code stream parameter.”, 0 JZ .EndStr ……… CALL PrintChar ;procedure that displays a ;single character INC BX ;move to the next char JMP .PrintLp Consider the following implementation of MyPrint MyPrint .EndStr: INC BX ;point at first byte beyond zero MOV [BP+2], BX ;save as a new return address PUSH BP POP AX MOVE BP, SP POP BX PUSH BX POP BP PUSH AX RET Monday, March 14, 2016 ECE291 – Lecture 7 Slide 22 of 31 Passing Parameters via a Parameter Block Consider simple subroutine that adds J and K together, storing the result in I. ParmBlock I RESW J RESW K RESW ;I, J, K must appear in this order …… LES bx, ParmBlock CALL AddEm PUSH AX MOV AX, [ES:BX+2] ;get J’s value ADD AX, [ES:BX+4] ;add in K’s value MOV [ES:BX], AX ;store result in I ;loads far pointer into ES:BX AddEm RET Monday, March 14, 2016 ECE291 – Lecture 7 Slide 23 of 31 Macros • A macro inserts a block of statements at various points in a program during assembly • Text substitutions made at compile time – NOT a procedure -- Code is literally dumped into the program – Parameter names are substituted – Useful for tedious programming tasks – Instantiated within code segment. Monday, March 14, 2016 ECE291 – Lecture 7 Slide 24 of 31 Macros (cont.) • Generic Format %macro MACRO_NAME numargs Your Code ... ... %{1} ... … %{2} ... Your Code ... JMP %%MyLabel Your Code ... %%MyLabel: ... %{N} ... Your Code ... %endmacro Monday, March 14, 2016 ECE291 – Lecture 7 Slide 25 of 31 Local Variable(s) in a Macro • A local variable is one that appears in the macro, but is not available outside the macro • We use the %%prefix for defining a local label – If the label MyLabel in the previous example is not define as local, the assembler will flag it with errors on the second and subsequent attempts to use the macro • Macros can be placed in a separate file – use %include directive to include the file with external macro definitions into a program – no EXTERN statement is needed to access the macro statements that have been included Monday, March 14, 2016 ECE291 – Lecture 7 Slide 26 of 31 Macros (cont.) Example: %macro DIV16 3 ; args: Result, X, Y ; Store into Result the signed result of X / Y ; Calculate Result = X / Y ; (all 16-bit signed integers) ; Destroys Registers AX,DX MOV AX, %{2} ; Load AX with Dividend CWD ; Extend Sign into DX IDIV %{3} ; Signed Division MOV %{1}, AX ; Store Quotient %endmacro • Monday, March 14, 2016 ECE291 – Lecture 7 Slide 27 of 31 Macros (cont.) • Example: Using the macro in a program ; Variable Section varX1 DW 20 varX2 DW 4 varR DW ? ; Code Section DIV16 word [varR],word [varX1],word [varX2] Will actually generate the following code (You won't actually see this unless you debug the program). MOV AX, word [varX1] CWD IDIV word [varX2] MOV word [varR], AX Monday, March 14, 2016 ECE291 – Lecture 7 Slide 28 of 31 Macros vs Procedures Proc_1 CALL MOV AX, 0 …... MOV BX, AX CALL MOV CX, 5 …... RET %macro Macro_1 Proc_1 Proc_1 Macro_1 0 MOV AX, 0 MOV BX, AX MOV CX, 5 …… Macro_1 %endmacro Monday, March 14, 2016 ECE291 – Lecture 7 Slide 29 of 31 Macros vs Procedures (cont.) • In the example the macro and procedure produce the same result • The procedure definition generates code in your executable • The macro does not emit any code when processing the statements between the %macro and %endmacro – Upon encountering Macro_1 in the mnemonic field, NASM assembles every statement between the %macro and %endmacro directives and emits that code to the output file – At run time, the processor executes these instructions without the call/ret overhead Monday, March 14, 2016 ECE291 – Lecture 7 Slide 30 of 31 Macros vs Procedures (cont.) • Advantage of using macros – execution of macro expansion is usually faster (no call and ret) than the execution of the same code implemented with procedures • Disadvantage – assembler copies the macro code into the program at each macro invocation – if the number of macro invocations within the program is large then the program will be much larger than when using procedures Monday, March 14, 2016 ECE291 – Lecture 7 Slide 31 of 31