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

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.

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 7 Years Ago by mathematician: n/a

This article has been dead for over six months. Start a new discussion instead.