The routines below do a mem_set for longs, words and bytes plus an add to array with value for longs, words and bytes. The instructions lods (load string) and stos (store string) are used.
For the add routines both ESI and EDI are used - lods uses ESI and stos uses EDI
For the set routines only EDI is used for stos
MemSuff
#include <stdio.h>
// protos
void add_arrl(int * arr, int i, size_t n);
void mem_setl(int * arr, int i, size_t n);
void add_arrw(short * arr, short i, size_t n);
void mem_setw(short * arr, short i, size_t n);
void add_arrb(char * arr, char i, size_t n);
void mem_setb(char * arr, char i, size_t n);
void __declspec(naked) add_arrl(int * arr, int i, size_t n)
{
_asm("pushl %esi");
// save register
_asm("pushl %edi");
// save register
_asm("movl 12(%esp),%edi"); // get array address in edi
_asm("movl %edi,%esi"); // get array address in esi
_asm("movl 16(%esp),%edx"); // the value in edx
_asm("movl 20(%esp),%ecx"); // the number of array elements
_asm("cmpl $0,%ecx");
_asm("jle exit1");
// bail out if zero or less
_asm("cld");
// ESI and EDI are incremented
_asm("start1:");
_asm("lodsl");
// get current array element into EAX
_asm("addl %edx,%eax"); // add value
_asm("stosl");
// put it back into the array
_asm("loop start1");
// loop until (ECX==0)
_asm("exit1:");
_asm("popl %edi");
_asm("popl %esi");
_asm("ret");
}
void __declspec(naked) add_arrw(short * arr, short i, size_t n)
{
_asm("pushl %esi");
_asm("pushl %edi");
_asm("movl 12(%esp),%edi");
_asm("movl %edi,%esi");
_asm("movl 16(%esp),%dx"); // the value in dx
_asm("movl 20(%esp),%ecx");
_asm("cmpl $0,%ecx");
_asm("jle exit2");
_asm("cld");
_asm("start2:");
_asm("lodsw");
_asm("addw %dx,%ax");
_asm("stosw");
_asm("loop start2");
_asm("exit2:");
_asm("popl %edi");
_asm("popl %esi");
_asm("ret");
}
void __declspec(naked) add_arrb(char * arr, char i, size_t n)
{
_asm("pushl %esi");
_asm("pushl %edi");
_asm("movl 12(%esp),%edi");
_asm("movl %edi,%esi");
_asm("movl 16(%esp),%dl");
// the value in dl
_asm("movl 20(%esp),%ecx");
_asm("cmpl $0,%ecx");
_asm("jle exit3");
_asm("cld");
_asm("start3:");
_asm("lodsb");
_asm("addb %dl,%al");
_asm("stosb");
_asm("loop start3");
_asm("exit3:");
_asm("popl %edi");
_asm("popl %esi");
_asm("ret");
}
void __declspec(naked) mem_setl(int * arr, int i, size_t n)
{
_asm("pushl %edi");
// save register
_asm("movl 8(%esp),%edi"); // get array address
_asm("movl 12(%esp),%eax"); // the value in eax
_asm("movl 16(%esp),%ecx"); // the number of array elements
_asm("cmpl $0,%ecx");
_asm("jle exit4");
// bail out if zero or less
_asm("cld");
// EDI will be incremented
_asm ("rep");
_asm ("stosl");
_asm("exit4:");
_asm("popl %edi");
_asm("ret");
}
void __declspec(naked) mem_setw(short * arr, short i, size_t n)
{
_asm("pushl %edi");
_asm("movl 8(%esp),%edi");
_asm("movw 12(%esp),%ax"); // the value in ax
_asm("movl 16(%esp),%ecx");
_asm("cmpl $0,%ecx");
_asm("jle exit5");
_asm("cld");
_asm ("rep");
_asm ("stosw");
_asm("exit5:");
_asm("popl %edi");
_asm("ret");
}
void __declspec(naked) mem_setb(char * arr, char i, size_t n)
{
_asm("pushl %edi");
_asm("movl 8(%esp),%edi");
_asm("movw 12(%esp),%al"); // the value in al
_asm("movl 16(%esp),%ecx");
_asm("cmpl $0,%ecx");
_asm("jle exit6");
_asm("cld");
_asm ("rep");
_asm ("stosb");
_asm("exit6:");
_asm("popl %edi");
_asm("ret");
}
int main(void)
{
int arrl[2000];
short arrw[2000];
char arrb[2000];
mem_setl(arrl, 3, 2000);
add_arrl(arrl, 7, 2000);
for(int i=1990; i<2000; i++)
printf("%d ", arrl[i]);
printf("\n");
mem_setw(arrw, 2, 2000);
add_arrw(arrw, 9, 2000);
for(int i=1990; i<2000; i++)
printf("%d ", arrw[i]);
printf("\n");
mem_setb(arrb, 3, 2000);
add_arrb(arrb, 10, 2000);
for(int i=1990; i<2000; i++)
printf("%d ", arrb[i]);
printf("\n");
return 0;
}