Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Assembler My.cpp: определяет точку входа для консольного приложения.
- //
- #include "stdafx.h"
- #include "stdlib.h"
- #include <stdio.h>
- #include <string.h>
- #include <conio.h>
- //#include <math.h>
- #include <cmath>
- char * algorithm1(char * input_string) //aaa !! bb1bb cc2cc -> aaa !! bbaaabb ccbb1bbcc
- {
- int length = strlen(input_string);
- char * output_string = new char[length];
- unsigned long * word_array = new unsigned long[length];
- __asm{
- xor eax, eax
- mov esi,[input_string] // копируем адрес указателя в регистр esi
- mov ebx, word_array // помещаем в регистр адрес адрес word_array по тестам здесь [] не имеют никакого значения
- mov [ebx], 0
- mov ecx, 1
- cycle_1: // в цикле бежим по исходной строке
- lodsb // считывает символ(байт) на который указывает регистр esi и помещает в al. увеличивает esi на 1
- cmp al, 0 // сравниваем с 0. 0 - терминальный символ, конец строки в си. cmp x ,y
- je exit_1 // je - если x == y. выходим из цикла.
- cmp al, 47 // сравниваем с кодом символа '0'
- jb less47_1 // JB Jump if below (X < Y) CF=1
- jae above47_1 // JAE Jump if above or equal (X >= Y) CF=0
- jmp cycle_1 // безусловный переход.
- // далее идут проверки, которые должны определять разделители как символы, коды которых принадлежат [1,47) и (57,65). остальное символы.
- less47_1:
- jmp separator_1 // если меньше чем код символа '0' 47, то считать разделителем.
- above47_1:
- cmp al, 57
- ja above57_1 // JA Jump if above (X > Y) CF=0 & ZF=0
- jbe symbol_1 // JBE Jump if below or equal (X <= Y) CF=1 or ZF=1
- above57_1:
- cmp al, 65
- jae symbol_1
- jb separator_1
- symbol_1:
- cmp ecx, 1
- je local_mark_1
- jne cycle_1
- local_mark_1:
- mov [ebx], esi // помещаем в ячейку, на которую указывает ebx (word_array), адрес начала слова
- sub [ebx], 1
- add ebx, 4 // увеличиваем ebx на 4 байта, т.к. адреса 32-битные.
- xor ecx, ecx // обнуляем ecx - это флаг в данном алгоритме ecx==1 - предыдущий символ - разделитель
- jmp cycle_1
- separator_1:
- cmp ecx, 1 // сравниваем флаг с 1.
- jne local_mark_2 // если != то
- jmp cycle_1
- local_mark_2:
- mov ecx, 1 // устанавливаем его в 1.
- jmp cycle_1
- exit_1:
- xor ecx, ecx
- mov [ebx], ecx // добавляем 0 адрес, как символ конца массива
- // конец первого алгоритма по нахождению и выделению слов. в итоге получаем "массив" адресов, каждый из которых указывает на начало нового слова в input_string
- // вторая часть алгоритма проходит от начала каждого слова до начала следующего.
- // само слово переворачивает и если после слова были разделители, дописывает их после слова.
- mov ebx, word_array // указатель на ячейку памяти, в которой хранится адрес первого слова (если оно было)
- mov edi, [output_string]
- mov esi, [ebx]
- cycle_2:
- lodsb
- jmp procchar
- charprocessed:
- cmp ecx, -1
- je charnotnumber
- jmp procwordmas
- wordmasprocessed:
- charnotnumber:
- stosb
- jmp cycle_2
- procchar:
- mov ecx, -1
- cmp al, 0 // сравниваем с 0. 0 - терминальный символ, конец строки в си. cmp x ,y
- je exit_3 // je - если x == y. выходим из цикла.
- cmp al, 47 // сравниваем с кодом символа '0'
- jb less47_3 // JB Jump if below (X < Y) CF=1
- jae above47_3 // JAE Jump if above or equal (X >= Y) CF=0
- jmp charprocessed // безусловный переход.
- // далее идут проверки, которые определяют является ли символ числом или нет
- less47_3:
- jmp notnumber_3 // если меньше чем код символа '0' 47, то считать разделителем.
- above47_3:
- cmp al, 57
- ja notnumber_3 // JA Jump if above (X > Y) CF=0 & ZF=0
- jbe number_3 // JBE Jump if below or equal (X < Y) CF=1 or ZF=1
- number_3:
- mov ecx, eax
- sub ecx, 49
- jmp charprocessed
- notnumber_3:
- jmp charprocessed
- procwordmas:
- push ebx
- push esi
- cmp ecx, 0
- je aftercycle_3
- cmp [ebx], 0
- je endcycle_4
- cycle_3:
- add ebx, 4
- cmp [ebx], 0
- je endcycle_4
- loop cycle_3
- aftercycle_3:
- mov esi, [ebx]
- cycle_4:
- lodsb
- jmp chekforsymbol
- endcycle_4:
- pop esi
- pop ebx
- jmp cycle_2
- chekforsymbol:
- cmp al, 0 // сравниваем с 0. 0 - терминальный символ, конец строки в си. cmp x ,y
- je endcycle_4 // je - если x == y. выходим из цикла.
- cmp al, 47 // сравниваем с кодом символа '0'
- jb less47_5 // JB Jump if below (X < Y) CF=1
- jae above47_5 // JAE Jump if above or equal (X >= Y) CF=0
- jmp endcycle_4 // безусловный переход.
- // далее идут проверки, которые определяют является ли символ разделителем или нет
- less47_5:
- jmp separator_5 // если меньше чем код символа '0' 47, то считать разделителем.
- above47_5:
- cmp al, 57
- ja above57_5 // JA Jump if above (X > Y) CF=0 & ZF=0
- jbe symbol_5 // JBE Jump if below or equal (X <= Y) CF=1 or ZF=1
- above57_5:
- cmp al, 65
- jae symbol_5
- jb separator_5
- symbol_5:
- stosb
- jmp cycle_4
- separator_5:
- jmp endcycle_4
- exit_3:
- mov al, 0
- stosb
- }
- return output_string;
- }
- void algorithm2(int * input_array, int len1, int *max, int *xmax, int *min, int *xmin) // находит минимальный и максимальный элемент в массиве и определяет количество вхождений. работает с unsigned integer
- {
- _asm {
- //ecx - счётчик цикла
- //ebx - указатель на элемент массива
- //eax - max
- //edx - min
- //esi - xmax
- //edi - xmin
- mov ebx, [input_array]
- mov eax, [ebx]
- mov edx, [ebx]
- mov esi, 1
- mov edi, 1
- xor ecx, ecx
- dec ecx
- cycle:
- inc ecx
- cmp ecx, len1
- je exit_1
- checkmax:
- cmp [ebx + ecx*4], eax //a[n], max [ebx + ecx*4] - адресная арифметика. адрес ebx с смещением номер элемента * 4 байта
- ja aNgreaterMax //(a[n]>max)
- checkmin:
- cmp [ebx + ecx*4], edx //a[n], min
- jb aNlessMin //(a[n]<min)
- checkequalmax:
- cmp [ebx + ecx*4], eax //a[n], max
- je aNequalMax //(a[n]=max)
- checkequalmin:
- cmp [ebx + ecx*4], edx //a[n], min
- je aNequalMin //(a[n]=min)
- jmp cycle
- aNgreaterMax:
- mov eax, [ebx + ecx*4]
- mov esi, 1
- jmp cycle
- aNlessMin:
- mov edx, [ebx + ecx*4]
- mov edi, 1
- jmp cycle
- aNequalMax:
- inc esi
- jmp checkequalmin
- aNequalMin:
- inc edi
- jmp cycle
- exit_1:
- mov ecx, [max]
- mov [ecx], eax
- mov ecx, min
- mov [ecx], edx
- mov ecx, xmax
- mov [ecx], esi
- mov ecx, xmin
- mov [ecx], edi
- }
- }
- void algorithm3(double mass[], double x, int n, double epsilon, double d) // считает сумму ряда в наборе точек cos(x) + ... + cos((2n-1)x)/(2n-1)
- {
- int i = 1;
- int y = 0; //y=2n-1
- int two = 2;
- int one = 1;
- double result = 0.0;
- int maxsumn = 1000;
- __asm {
- mov ecx, n
- mov eax, maxsumn
- inc eax
- mov ebx, mass
- xor edx, edx
- finit // инициализация сопроцессора
- fld x
- fld epsilon // загружает точность
- fldz // команда загрузки константы 0, для последующей корректной работы, так как в регистрах может находится что угодно по-умолчанию
- fldz
- fldz
- fincstp
- bigcycle:
- repeat:
- fiadd i // st(0) = n команда сопроцессора, для суммирования регистра с целочисленным значением fadd для вещественного.
- fimul two // st(0) = 2*n команда для умножение на целочисленное значение
- fisub one // st(0) = 2*n - 1
- fist y // y = st(0) комнада сохранения значения из вершины стека в память, не сдвигая стек. для целочисленного.
- fmul st(0), st(3) // st(0) = (2*n - 1)*x
- fcos // st(0) = cos((2*n - 1)*x) трансцендентная команда st(0) = cos(st(0))
- fidiv y // st(0) = cos((2*n - 1)*x)/(2*n - 1)
- fadd st(1), st(0) // fadd приёмник, источник (приёмник = приёмник + источник)
- inc [i]
- cmp eax, i
- jbe exit1 // (n<=i)?
- fdecstp // Уменьшает указатель стека на 1
- fadd st(0), st(2)
- fabs // модуль числа st(0) = abs(st(0))
- fucom st(3) // сравнение с вершиной стека значения источника. если дописать p
- fstsw ax // С помощью команды "FSTSW AX" программа может переписать содержимое регистра состояния сопроцессора в регистр AX центрального процессора.
- sahf // содержимое регистра AH можно переписать в регистр флагов центрального процессора при помощи команды SAHF. можно использовать стандартные команды перехода je, ja, etc.
- fsub st(0), st(0) // обнуление вершины
- fincstp // Увеличивает указатель стека на 1
- jbe exit1
- fsub st(0), st(0)
- jmp repeat
- exit1:
- fsub st(0),st(0)
- fincstp
- fst QWORD PTR [ebx + edx*8] //команда сохранения значения из вершины стека в память, не сдвигая стек. для вещественного.
- fsub st(0), st(0)
- fdecstp
- fadd d
- fadd st(3), st
- fsub st(0), st(0)
- inc edx
- mov [i], 1
- loop bigcycle
- }
- }
- void algorithm4(double mass[], double x, int n, double d) // считает значение функции в нескольких точках 0.5ln(ctg(x/2))
- {
- int two = 2;
- double y = 0.5;
- double result = 1;
- _asm {
- finit
- mov ecx, n // в ecx n = количество повторений или длина массива
- mov ebx, mass // в ebx адрес массива для результирующих значений
- xor edx, edx // в edx номер текущего жлемента массива
- fld d
- fldl2e // загрузка log 2 (e)
- bigcycle:
- fld x // загрузка x
- fidiv two // st(0) = st(0)/2
- fptan // st(0) = sin(x) st(1) = cos(x)
- fdivr st(1), st(0) // st(1) = st(1)/st(0)
- fsub st(0), st(0) //
- fadd y //
- fxch st(1) //
- fyl2x // st(0) = y(st(1)) log 2 x(st(0))
- fdiv st(0), st(1) // st(0) = y ln 2 x
- fst QWORD PTR [ebx + edx*8]
- fsub st(0), st(0)
- fadd x
- fadd st(0), st(2)
- fst x
- fsub st(0), st(0)
- fincstp
- inc edx
- loop bigcycle
- }
- }
- double RootMeanSquareError(double *mass1, double *mass2, int n) //eugen version
- {
- _asm{
- mov ecx, n
- mov eax, mass1
- mov ebx, mass2
- finit
- fldz
- cycle:
- fld QWORD PTR [eax + 8*ecx - 8]
- fld QWORD PTR [ebx + 8*ecx - 8]
- fsubp st(1), st(0) // st(1) = mass1[i]-mass2[i] и извлекаем вершину стека (постфикс p)
- fmul st(0), st(0) // (mass1[i]-mass2[i])^2
- faddp st(1), st(0) // st(1) = st(1) + (mass1[i]-mass2[i])^2 также извлекаем вершину. st(0) теперь сумма
- loop cycle
- fild n // st(0) = n
- fdivp st(1), st(0) // делим st(1)/st(0) - summ/n
- fsqrt // функция возвращает значение, находящееся в st(0)
- }
- }
- inline double log2(double x)
- {
- static const double xxx = 1.0/log(2.0);
- return log(x)*xxx;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- int leng = 14;
- double *mass1 = new double[leng];
- double *mass2 = new double[leng];
- double x = 0.120796;
- double epsilon = 0.05;
- double step = 0.05;
- while (1)
- {
- printf("n = ");
- scanf("%i", &leng);
- printf("\nx = ");
- scanf("%f", &x);
- printf("\nepsilon = ");
- scanf("%f", &epsilon);
- printf("\nstep = ");
- scanf("%f", &step);
- algorithm3(mass1, x, leng, epsilon, step);
- algorithm4(mass2, x, leng, step);
- printf("\nYour result:\n");
- for(int i = 0; i < leng; i++)
- {
- printf("ryad(%f) - %i - %e\n", x + i*step, i+1, mass1[i]);
- printf("func(%f) - %i - %e\n\n", x + i*step, i+1, mass2[i]);
- }
- printf("RootMeanSquareError %e\n\n", RootMeanSquareError(mass1, mass2, leng)); getch();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement