/** * @brief ACSO fuctions: transcript between c and asm * * @copyright 2020 ACSO transcript * @author Adrian Panaintescu * * @details Simple functions written in cpp and "asm" organized on namespace, being available both variants as language * * @file * * @ingroup * */ #include using namespace std; namespace cc { // Structura pentru un numar complex struct complex { int re, im; }; namespace c { // Afiseaza diferenta intre doua numere void dif(int a, int b) { cout << a - b << endl; } // Afiseaza descrescator numerele in mod recusiv void afis(unsigned n) { if (n == 0) return; cout << n << endl; afis(n - 1); } // Calculeaza factorialul unui numar recursiv unsigned factorial(unsigned n) { if (n < 2) return 1; return n * factorial(n - 1); } // Apeleaza funtia dif void call_dif() { dif(10, 7); } // Calculeaza suma numelor complexe a si b // Rezultatul va ajunge in c void complex_suma(complex* a, complex* b, complex* c) { c->im = a->im + b->im; c->re = a->re + b->re; } // Calculeaza suma unui vector int vector_suma(int* t, int n) { int s = 0,i; for (i = 0; i < n; i++) { s += t[i]; } return s; } // Returneaza elementul unuei matrice 3x3 int matrice_element(int x[][3], int i, int j) { return x[i][j]; } // Calculeaza suma unei matrice creata dinamic 3x3 // int** x = new int* [3]; // for (int i = 0; i < 3; i++) // x[i] = new int[3]; int matrice_suma(int** x) { int s = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { s += x[i][j]; } } return s; } } namespace asmb { // Afiseaza diferenta intre doua numere void dif(int a, int b) { int x; _asm { push eax mov eax, a sub eax, b mov x, eax pop eax } cout << x << endl; } // Afiseaza descrescator numerele pana la n // in mod recusiv void afis(unsigned n) { _asm { cmp n, 0 je afara } cout << n << endl; _asm { dec n push n call afis add esp, 4 afara: } } // Calculeaza factorialul unui numar recursiv unsigned factorial(unsigned n) { _asm { push ebx mov ebx, n cmp ebx, 2 jae not_conditie mov eax, 1 jmp out_fct not_conditie : dec ebx push ebx call factorial add esp, 4 mul n out_fct : pop ebx } } // Apeleaza funtia dif void call_dif() { _asm { push dword ptr 7 push dword ptr 10 call dif add esp, 8 } } // Calculeaza suma numelor complexe a si b // Rezultatul va ajunge in c void complex_suma(complex* a, complex* b, complex* c) { _asm { add_re: mov eax, a mov ebx, [eax] mov eax, b add ebx, [eax] mov eax, c mov[eax], ebx add_im : mov eax, a mov ebx, [eax + 4] mov eax, b add ebx, [eax + 4] mov eax, c mov[eax + 4], ebx } } // Calculeaza suma unui vector // se foloseste deferentierea int vector_suma(int* t, int n) { _asm { mov eax, 0 mov ebx, 0 mov ecx, t bucla_fct : cmp ebx, n jge afara_fct add eax, [ecx + ebx * 4] inc ebx jmp bucla_fct afara_fct : } } // Returneaza elementul unuei matrice 3x3 int matrice_element(int x[][3], int i, int j) { _asm { push ebx push ecx push esi mov esi, x mov ebx, i mov ecx, j mov eax, 3 imul ebx add ecx, eax mov eax, [esi + ecx * 4] pop esi pop ecx pop ebx } } // Calculeaza suma unei matrice creata dinamic // int** x = new int* [3]; // for (int i = 0; i < 3; i++) // x[i] = new int[3]; int matrice_suma(int** x) { _asm { push ebx push ecx mov eax, 0 mov ebx, 0 bucla_i : cmp ebx, 3 jge afara_i mov ecx, 0 bucla_j : cmp ecx, 3 jge afara_j mov edx, x mov edx, [edx + ebx * 4] add eax, [edx + ebx * 4] inc ecx jmp bucla_j afara_j : inc ebx jmp bucla_i afara_i : pop ecx pop ebx } } } } void exercices(){ /* @Title: Exercitiu 1 * * @Enunt: Fie următorul program care calculează factorialul unui număr. Să se înlocuiască linia de cod din interiorul buclei for (f = f * i) cu un bloc de cod asm, cu obţinerea aceluiaşi efect. Pentru simplificare, vom considera că rezultatul nu depăşeşte 4 octeţi. * * @Category: Folosirea instructiunei mul si imul * / unsigned int n = 10, i, f = 1; for (i = 1; i <= n; i++) { // f = f * i; in asm _asm { mov eax, f mul i mov f, eax } } printf("%u\n", f); /* End Exerctiu 1 */ /* @Title: Exercitiu 2 * * @Enunt: Fie următorul program. Să se înlocuiască liniile 4 şi 5 cu un bloc de cod asm, cu obţinerea aceluiaşi efect. * * @Category: Folosirea instructiunei div si idiv * / unsigned a = 500007, b = 10, c, d; _asm { mov edx, 0 mov eax, a mov ebx, b div ebx mov c, eax mov d, edx } // c = a / b; // d = a % b; printf("%u %u\n", c, d); /* End Exerctiu 2 */ } int main() { exercices(); /* Test: dif * / cc::c::dif(5, 2); cc::asmb::dif(5, 2); /* End Test: dif */ /* Test: afis * / cc::c::afis(5); cc::asmb::afis(5); // call afis with asm _asm { push dword ptr 5 call cc::asmb::afis add esp, 4 } /* End Test: afis */ /* Test: factorial * / cout << cc::c::factorial(6) << " " << cc::asmb::factorial(6); /* End Test: factorial */ /* Test: call_dif * / cc::c::call_dif(); cc::asmb::call_dif(); /* End Test: call_dif */ /* Test: complex_suma * / cc::complex a = { 2,5 }, b = { 3,11 }, c; cc::c::complex_suma(&a, &b, &c); cout << c.re << " + " << c.im << "i" << endl; cc::asmb::complex_suma(&a, &b, &c); cout << c.re << " + " << c.im << "i" << endl; /* End Test: complex_suma */ /* Test: vector_suma * / int t[] = { 1, 9, 4, 12, 3 }; int suma = 0, *p = t; cout << cc::c::vector_suma(t, 5) << endl << cc::asmb::vector_suma(t, 5); /* End Test: vector_suma */ /* Test: matrice_element * / int p[3][3] = { 0, 1, 5, 7, 9, 2, 14, 13, 12 }; cout << cc::c::matrice_element(p, 2, 2) << endl << cc::asmb::matrice_element(p, 2, 2); /* End Test: matrice_element */ /* Test: matrice_suma * / int** v; v = new int* [3]; for (int i = 0; i < 3; i++) { v[i] = new int[3]; } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { v[i][j] = 1; } } cout << cc::c::matrice_suma(v) << endl << cc::asmb::matrice_suma(v); /* End Test: matrice_suma */ return 0; }