A procedure called from C should preserve the values of SI, DI, SS, and DS (in addition to BP, which is already saved). You should push any register value that your procedure modifies onto the stack after setting up the stack frame and allocating local storage, but prior to entering the main body of the procedure. Registers that your procedure does not alter need not be preserved.
Warning:
Routines that your assembly-language procedure calls must not alter the SI, DI, SS, DS, or BP registers. If they do, and you have not preserved the registers, they can corrupt the calling program's register variables, segment registers, and stack frame, causing program failure. If your procedure modifies the direction flag using the STD or CLD instructions, you must preserve the flags register.
The following example shows an entry sequence that sets up a stack frame, allocates 4 bytes of local data space on the stack, then preserves the SI, DI, and flags registers.
push bp ; Save caller's stack frame.
mov bp,sp ; Establish new stack frame.
sub sp,4 ; Allocate local data space.
push si ; Save SI and DI registers.
push di
pushf ; Save the flags register.
...
In the preceding example, you must exit the procedure with the following code:
popf ; Restore the flags register.
pop di ; Restore the old value in the DI
register.
pop si ; Restore the old value in the SI
register.
mov sp,bp ; Restore the stack pointer.
pop bp ; Restore the frame pointer.
ret ; Return to the calling routine.
If you do not issue the preceding instructions in the order shown, you will place incorrect data in registers. Follow the rules below when restoring the calling program's registers, stack pointer, and frame pointer:
Pop all registers that you preserve in the reverse order from which they were pushed onto the stack. So, in the preceding example, SI and DI are pushed, and DI and SI are popped.
Restore the stack pointer by transferring the value of BP into SP before restoring the value of the frame pointer.
Always restore the frame pointer last.