0

This is an example program that I am studying so that i can make my own mixed mode assembly/C program.

I am having trouble understanding on the assembly code, why I have to push SI twice at different times and only pop it out once. Also why push and pop DI when it's not used. I am confused from when I have push SI the second time.

/* An example to illustrate C function -> assembly -> a C function.
This program calls the assembly language procedure in file MARKS_A.ASM.
The program outputs min, max, and rounded average of two marks. */

#include <stdio.h>
 int main(void)
 {     	int mark1,mark2, min, max, av;
 	int find_avg(int, int);
        	extern  void stats(int, int, int*, int*, int*);
        	scanf("%d%d",&mark1,&mark2);
        	stats(mark1,mark2, &min, &max, &av);
	printf("Min = %d, Max = %d, Av = %d\n", min, max, av);
        	return 0;   }


  /*********************************************************
     * Returns the rounded average required by the assembly 
    * procedure STATS in file MARKS_A.ASM.*/

	int find_avg(int total, int number)     {
        	return((int)((double)total/number + 0.5)); }
;----------- --------- --------- --------- --------- --------- -­
; Assembly program example to show call to a C function.
; This procedure receives a marks array and class size
; and returns minimum, maximum, and rounded average marks.
;----------- --------- --------- --------- --------- --------- -­
.MODEL SMALL
EXTRN _find_avg:PROC
.CODE
PUBLIC _stats
_stats PROC 
push BP
mov BP,SP
push SI
push DI


mov AX,[BP+4] ; AX := mark1
mov DX,[BP+6] ; DX := mark2
cmp AX,DX ; put min into AX and max into DX
jl next
xchg AX,DX
next:
: mov SI,AX ; SI gets sum
add SI,DX

mov BX,[BP+8] ; return minimum
mov [BX],AX
mov BX,[BP+10] ; return maximum
mov [BX],DX 

; now call find_avg C function to compute average

mov AX,2 ;push number of marks
push AX
push SI ;push sum of marks
call _find_avg ; returns average in AX
add SP,4 ; clear stack
mov BX,[BP+12] ; return average
mov [BX],AX 
pop DI
pop SI
pop BP
ret ; NOTE calling program clears stack
_stats ENDP
END
3
Contributors
2
Replies
3
Views
7 Years
Discussion Span
Last Post by mathematician
0

The C compiler will cause the executable to save and restore certain registers before and after a call, but not others, so the point of this exercise must be to get you thinking along those lines.

Your assembly program calls the external function "find_avg", so you don't know that DI isn't used. The first time you push SI is to preserve it for the return to the C program.

The second time you push SI is to put an argument on the stack for the "find_avg" function. The "add SP,4" effectively removes those arguments from the stack, otherwise the C program would think they were part of the result.

0

Old time compilers use si and di to store register variables, so they are routinely saved on the stack. It looks to me as if si is being pushed a second time because it is being passed as an argument to the find_avg() function. It, along with ax, is removed with the add sp, 4 instruction. (In 16 and 32 bit C all arguments are passed on the stack).

Edited by mathematician: n/a

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.