Modular Programming Stack Frames and HighLevel Language Interfacing
















![A Recursive Procedure in ASM factorial: mov eax, [esp+4] ; get n cmp eax, A Recursive Procedure in ASM factorial: mov eax, [esp+4] ; get n cmp eax,](https://slidetodoc.com/presentation_image_h2/7e8aff6d34acdc20e207b963fbfaced4/image-17.jpg)












![Memory Allocation mem. c* Stack Setup 30 Register Usage ebp-72 z[16] EBX =a ebp– Memory Allocation mem. c* Stack Setup 30 Register Usage ebp-72 z[16] EBX =a ebp–](https://slidetodoc.com/presentation_image_h2/7e8aff6d34acdc20e207b963fbfaced4/image-30.jpg)


- Slides: 32

Modular Programming, Stack Frames, and High-Level Language Interfacing Chapter 8 1

Modular Programming § Large projects need to be broken into small modules with clean interfaces § The way to program a module should only depend on the interfaces provided by other modules – not their implementation § One possibility would be to place groups of related procedures into different files and then include them with the include directive § The include directive instructs the assembler to include the file (at assembly time) at the place of the directive § We must then insure that the code will be placed in the. code segment and the data will be placed in the. data segment 2

Modular Programming (cont. ) § Hence, in each file, we should always put. code before the code and. dada before the data. Ex: File my_prog. asm. 386. model flat include csi 2121. inc. data msg 1 db "In main", 10, 0. code main: putstr msg 1 call proc. A call proc. B ret include proc. A. asm include proc. B. asm end 3 File proc. A. asm. code proc. A proc putstr msg 2 ret proc. A endp. data msg 2 db "In proc. A", 10, 0 File proc. B. asm. code proc. B proc putstr msg 3 ret proc. B endp. data msg 3 db "In proc. B", 10, 0

Modular Programming (cont. ) § Hence, by doing Bcc 32 my_prog. asm § The assembler will create a single object file my_prog. obj which will contain all the included code and data § The scope of each name used (in any included file) will be the object module in which they will be assembled. Here it is my_prog. obj § Hence an error will be detected by the assembler if two different included files use the same name § Hence this method of included files should be avoided for large projects § Instead, we should assemble each file separately to obtain a separate object module for each file and, thus, have a private namespace for each file § Make sure, however, to use the. 386, . MODEL FLAT, and END directives in each file. 4

Separately Assembled Modules § However any module that wants to be used need to provide at least one name to be used by others § Use the directive PUBLIC to enable other modules to use names defined in the module where PUBLIC is. Ex: public proc. A, var. C, label. B § Note that the usage is the same for any kind of names (procedures, variables. . . ) § Use the directive EXTRN to declare names that are defined in other modules § But now we need to provide the qualifiers: § PROC for procedure names § BYTE, WORD, DWORD. . . for variable names § Example: extrn proc. A: proc, var. A: dword, var. B: word § Place the directives extrn and public just after. model flat 5

Exampl e File my_prog. asm. 386. model flat extrn proc. A: proc, proc. B: proc include csi 2121. inc. data msg 1 db "In main", 10, 0. code main: putstr msg 1 call proc. A call proc. B ret end 6 File proc. A. asm. 386. model flat public proc. A include iomacros. inc. code proc. A: putstr msg 1 ret. data msg 1 db "In proc. A", 10, 0 end File proc. B. asm. 386. model flat public proc. B include iomacros. inc. code proc. B: putstr msg 1 ret. data msg 1 db "In proc. B", 10, 0 end

Example (cont. ) § To assemble each file separately and link them do: bcc 32 –c proc. A. asm bcc 32 –c proc. B. asm bcc 32 my_prog. asm proc. A. obj proc. B. obj § The –c is the “compile only” option: it only produces an object file § The last command will produce my_prog. obj and link all the. obj files to produce my_prog. exe § All. data segments will be concatenated into a single. data segment and all. code segments will be concatenated into a single. code segment § Each. asm file now provides a separate namespace since each file has been assembled separately § Note that all three files are using the same name msg 1. These refer to different memory locations since the assembler and linker will produce a different memory address for each variable msg 1. 7

The Program’s Entry Point § An executable program must have only one entry point (the address of the first instruction to execute). § This entry point must be called “_main” and made public when using bcc 32 to assemble and link § This is why I have included the following directives in csi 2121. inc (near to top of the file) public _main equ <_main> § The second directive makes “main” equivalent to “_main” so that “main” can be used instead to label the entry point. § But since a program can have only one entry point, these two directives must be present only in one. asm file: the one containing the entry point § If the macros in csi 2121. inc are needed in other modules, then include instead another file, called it iomacros. inc, which is identical to csi 2121. inc but does not contain these two directives (see previous example again) 8

Using Global Variables § A variable made public in one object module will be accessible to every other object module that will be linked into the same. exe file § As long as the other object modules are declaring this variable to be extern § Such a variable, which is said to be global, can be used by procedures to pass a value across different modules. § This mechanism increases the complexity of the interfaces (since every module must be aware of all the global variables) § Hence the number of global variables should be minimal 9

Global Variable Example File mp. asm. 386. model flat public var. A extrn proc. A: proc include csi 2121. inc File proc. A. asm. 386. model flat public proc. A extrn var. A: dword include iomacros. inc . data var. A dd ? . code proc. A: putint var. A ret end . code main: mov var. A, 333 call proc. A ret end To assemble and link, you can do: bcc 32 mp. asm proc. A. asm 10

Parameter Passing § We currently have two ways to pass parameters to a procedure § By using registers § By using global variables § However these mechanisms to pass parameters are not suited if we want § To use a variable number of parameters § To permit a procedure to call itself (for using recursion) § In these circumstances we can pass parameters via the stack § This is the mechanism of parameter passing used by high level languages 11

Stack Parameters § Suppose that we have a procedure, called IMUL 2, who’s task is to multiply two signed numbers, pushed onto the stack, and return the result into EAX. § Let us use IMUL 2 like this: push var. A ; push a dword variable push var. B ; another dword variable call IMUL 2 ; result in eax, stack unchanged add esp, 8 ; restore ESP 12 § We have assumed that IMUL 2 did not changed the stack: § ESP just after returning from IMUL 2 is pointing to the same place as it was just before calling IMUL 2. § But, since 8 bytes of parameters were pushed on the stack, we need to increase ESP by 8 after returning from IMUL 2 § Otherwise, ESP would be decreased by 8 at each IMUL 2 usage and, consequently, the stack could overflow if the 3 first statements were inside a loop § We say that the stack has been restored by the caller § This is the method used by C/C++ compilers

Stack Parameters (cont. ) § Given that IMUL 2 is called that way, we can write it like this: IMUL 2: push ebp mov ebp, esp mov eax, [ebp+12] imul eax, [ebp+8] pop ebp ret § We used EBP to access the stack parameters (not ESP) §Compilers are using this method. But, more simply, we could have used ESP instead. . . § These are called stack frames (or activation records) var. A var. B ret addr. ebp orig. after mov ebp, esp var. A var. B after ret 13 ebp esp

Stack Parameters (cont. ) § The other method is to let the called procedure the responsibility of restoring the stack §This is the method used by Pascal compilers § The caller would simply do push var. A push var. B call IMUL 2 ; do not increm. ESP § But the procedure would now use ret n to return §This performs a RET instruction and then increments ESP further by n 14 § The called procedure would now be: IMUL 2: push ebp mov ebp, esp mov eax, [ebp+12] imul eax, [ebp+8] pop ebp ret 8 §Since 8 bytes of parameters have been pushed onto the stack

Passing a Variable Number of Parameters § To pass a variable number § The called procedure: of arguments by the stack Add. Some proc just push, as the last push ebp parameter, the number of push ecx arguments mov ebp, esp §By popping this parameter, the procedure knows how mov ecx, [ebp+12]; arg count much arguments were xor eax, eax ; hold sum passed add ebp, 16 ; last arg § The caller: L 1: push 35 push – 63 push 23 push 3 ; # of args call Add. Some add esp, 16 15 add eax, [ebp] add ebp, 4 ; point to next loop L 1 pop ecx pop ebp ret Add. Some endp

Recursion 16 § A recursive procedure is one that calls itself § Recursive procedures can easily be implemented in ASM when parameter passing is done via the stack § Ex: a C implementation of factorial: int factorial(int n) { if (n<=1) { return 1; } else { return n*factorial(n-1); } } § An ASM caller needs to push the argument into the stack: push 8 call factorial ; result in EAX add esp, 4 ; restore the stack
![A Recursive Procedure in ASM factorial mov eax esp4 get n cmp eax A Recursive Procedure in ASM factorial: mov eax, [esp+4] ; get n cmp eax,](https://slidetodoc.com/presentation_image_h2/7e8aff6d34acdc20e207b963fbfaced4/image-17.jpg)
A Recursive Procedure in ASM factorial: mov eax, [esp+4] ; get n cmp eax, 1 ; n<=1? ja L 1 ; no, continue mov eax, 1 ; yes, return 1 jmp exit L 1: dec eax push eax ; factorial n-1 call factorial; result in eax add esp, 4 ; restore stack mov ebx, [esp+4]; get n mul ebx ; edx: eax = eax*ebx exit: ret ; eax = result 17 Stack usage on Factorial 3: 3 ret. add. in main 2 ret. add. in fact. 1 ret. add. in fact.

Exercises § Ex 1: Rewrite the factorial procedure when stack cleaning is done by the called procedure (ie: in the Pascal way) § Ex 2: Write a procedure who’s task is to fill with value 0 the first k bytes of a byte array. All parameters must be passed by the stack and stack cleaning must be done by the caller. Give an example of how this procedure would be called. § Ex 3: Rewrite the Add. Some procedure when stack cleaning is done by the called procedure (ie: in the Pascal way) 18

Why Interfacing with High Level Languages? § Good ASM programs give faster machine code than high level language (HLL) programs § because ASM code is closer to machine code § But it takes too long to develop large-scale applications in assembly language § instead we first write the application in a HLL § then, to optimize speed, we rewrite in ASM the parts of code that are executed most often § we do not need to write too much ASM code since, typically, the CPU spends most of its time in less then 10% of the application’s code 19

Two Methods for Mixing ASM and HLL Codes § ASM code in a separate ASM module 1) assemble the. asm file into a. obj module 2) compile HLL files into. obj modules 3) link together all. obj modules to obtain the. exe file § the most powerful method (and preserves modularity) § Inline ASM code (embedded with HLL code) § The easiest method (no linking issues involved). We just use a preprocessor directive like asm{. . . } to include asm instructions directly into the HLL code. § But this usually forces the compiler to generate sub optimal code outside the ASM region § We present here only the first method for the C language when using the C/C++ compiler from Borland: bcc 32. exe 20

Writing Separate ASM modules § Such an ASM module can contain: § Variables and procedures that will be used by other HLL modules § ASM instructions that uses variables and procedures defined in other HLL modules § Hence, the ASM programmer must know: § The memory model used by the HLL compiler (this is the flat memory model for bcc 32) § How external names are generated by the HLL compiler § The calling convention (of procedures) used by the HLL compiler 21

Generation of ASM code by the C compiler* § Is the only way to discover what the C compiler is really doing § To generate hello. asm from hello. c , just do: bcc 32 -S hello. c § Immediate observations: § uses the following 32 -bit segments named: _TEXT : for code _DATA : for data (and the stack) _BSS : for un-initialized data § you can remove all references to the ? debug macro and labels that are not used § I have cleaned up the file hello. asm and removed unused directives to obtain the simpler (but equivalent) file hello. Clean. asm 22

The Naming Convention of C Compilers § These compilers insert a “_” in front of all names used in C source files § “main” has been change to “_main” § “printf” has been changed to “_printf”. . § Hence, all public names in a ASM file that are to be used from a C source file should start with a “_” § Ex: if a C file contains a call to the my. Proc() function, then this procedure in a ASM file should be named _my. Proc § Names recognized by C compilers are case sensitive § Fortunately case sensitiveness for user defined names is preserved when using the bcc 32 command to assemble 23

Further Observations on hello. Clean. asm § Bcc 32 assumes, by default, that the entry point is _main and requires _main to be public § This is why I have included these 2 directives in csi 2121. inc public _main equ <_main> § The value returned by _main is in EAX § The argument of _printf (address of a null terminating string) is pushed on stack and stack cleanup is done by the caller 24

How to write an ASM procedure that is called by a C program? * § To discover how to do this, let us first write a C program comp. c that uses a C function § Then use bcc 32 to convert this C program into the ASM program comp. asm § We see that two bytes are allocated to a short int and 4 bytes to a int. In fact we have the following correspondence between C/C++ types and ASM types for bcc 32 C Data Type char, unsigned char short int, long pointer float double 25 Storage Bytes 1 2 4 4 4 8 ASM Type byte word dword qword

How to write an ASM procedure that is called by a C program? (cont. ) § To call f 1(), bcc 32 has generated the following instructions ; z = f 1(a, b, c, d); ; EAX = a, EDX = b, ECX = c, ESI = d push esi push ecx push edx push eax call _f 1 add esp, 16 § We see that arguments are pushed onto the stack by starting from the last one and that the stack is cleaned by the caller. This is known as the C calling convention. § Also: arguments passed to a function are pushed onto the stack as dwords (even when the corresponding types are only 2 bytes) § Notice that _f 1 does not preserve the content of ECX and EDX (but it preserves EBX and EBP). 26

How to write an ASM procedure that is called by a C program? (cont. ) § When a C function returns an integer value that is less or equal to 4 bytes, it is returned in EAX § But when a C function returns a float or a double, it is returned in ST(0) § Bcc 32 assumes that the content of EBX, EBP, ESI, and EDI will be preserved by a procedure: make sure to preserve them (you do not need to preserve the other registers). § Therefore, we can write the f 1() function in ASM and place it in the fff 1. asm file § Notice that I have optimized f 1() by removing one MOV and two MOVSX instructions and by using ESP to access the stack arguments. § The C caller is now fcomp. c and the fcomp. exe file is obtained by doing: bcc 32 fcomp. c fff 1. asm 27

Exercises § Ex 4: In C/C++, a function argument can be a pointer to a function. This enables us to construct functions that can use as an argument another function. An example would be a function who’s task is to find the maximum value of (another, arbitrarily chosen) function in some interval. How can you do this in ASM? Generate ASM code from a C compiler to find out § Ex 5: What is the difference between a C++ pointer and a C++ reference? What is the difference between passing a pointer and passing a reference to a function? Generate ASM code from a C compiler to find out 28

Memory Allocation § The mem. c program allocates storage for variables and arrays in various ways § Inspection of mem. asm reveals how it is done: § Variables are first allocated to registers and then to the stack § “Normal” arrays are allocated to the stack: EBP is used to access the array elements § Dynamic allocation with calloc() returns an offset address into EAX: array elements are stored starting at that address. The allocated memory block is located in the heap. 29
![Memory Allocation mem c Stack Setup 30 Register Usage ebp72 z16 EBX a ebp Memory Allocation mem. c* Stack Setup 30 Register Usage ebp-72 z[16] EBX =a ebp–](https://slidetodoc.com/presentation_image_h2/7e8aff6d34acdc20e207b963fbfaced4/image-30.jpg)
Memory Allocation mem. c* Stack Setup 30 Register Usage ebp-72 z[16] EBX =a ebp– 4 d ebp-76 z[15] ebp– 8 e ebp-80 z[14] ESI =b ebp-12 f ebp-84 z[13] EDI =c ebp-16 g ebp-88 z[12] ebp-20 h ebp-92 z[11] ebp-24 i ebp-96 z[10] ECX =m ebp-28 j ebp-100 z[9] ebp-32 k ebp-104 z[8] ebp-36 l ebp-108 z[7] EAX = count ebp-40 z[24] ebp-112 z[6] ebp-44 z[23] ebp-116 z[5] EDX =y ebp-48 z[22] ebp-120 z[4] ebp-52 z[21] ebp-124 z[3] ebp-56 z[20] ebp-128 z[2] ebp-60 z[19] ebp-132 z[1] ebp-64 z[18] ebp-136 z[0] ebp-68 z[17]

Memory Allocation (cont. ) § A static variable (in C) is defined with the keyword “static” § its value is preserved through successive invocations of the function inside which it is defined § A automatic variable (in C) is defined without the keyword “static” § its value is not preserved through successive invocations of the function inside which it is defined § Ex: static. asm is obtained from static. c § automatic variables are allocated on the stack The stack frame thus contains all the “environment” of a procedure § static variables are permanently allocated on the data segment and given a name 31

Win 32 Assembly § The bcc 32. exe automatically links with the import 32. library § This enable us to call directly most of the Win 32 API procedures § msgbox. asm is a minimal Win 32 assembly program that calls the Windows Message. Box. A procedure to display a message box § Note that: § Stack cleaning is done by the Win 32 procedure § Win 32 procedure names do not start with “_” § Practical Win 32 apps are much more complex than this one. . . 32