Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЭВМ и ВС отчет1.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.35 Mб
Скачать

Рисунок 1.1 – Схема алгоритма вычисления исходного выражения

1.4 Решение

#include "stdafx.h"

#include <stdio.h> // стандартный ввод/вывод

#include <iostream> // потоковый ввод/вывод

#include <locale.h>

// функция вычисления выражения (-2*с + d*82)/(a/4 - 1);

bool error = 0;

int calc(int a, int b, int c)

{

int result = 0;

__asm{

mov eax, a

mov ebx, b

mov ecx, c

Sar eax,1 ; арифметический сдвиг вправо на 1, <eax>=a/2

Sar eax,1 ; арифметический сдвиг вправо на 1, <eax>=a/4 dec eax ; <eax>=a/4-l

or eax, eax ; проверка на флаг нуля

je error1

push eax ; в стеке a/4-l

mov eax, 2 ; <eax>=2

imul ecx ; <edx:eax> = c*2

push eax ; в стеке c*2

mov eax, 82 ; <eax>=82

imul ebx ; <edx:eax> = b*82

pop ebx ; <ebx>= c*2

sub eax, ebx ; <eax>= b*82 - 2*c

pop ebx ; <ebx> = a/4-1

; готовимся к делению

cdq ; eax ==> edx:eax

idiv ebx ; <eax>=(-2*с + b*82)/(a/4 - 1)

mov result, eax ; result = eax

jmp end_1

error1:

mov error, 1

end_1:

}

return result; // возвращаем результат вычисления выражения

}

int _tmain(int argc, _TCHAR* argv[])

{

setlocale(LC_CTYPE,"rus");

printf("Лабораторная работа№1\n");

printf("Вариант: 3\n");

printf("Автор: Галанова Дарья\n");

printf("Группа: 6113\n");

printf("Задание:\n");

printf("Вычисление выражения (-2*с + b*82)/(a/4 - 1)\n\n");

printf("\n");

int a, b, c;

printf("Введите a: ");// стандартный вывод

std::cin >> a;// потоковый ввод

printf("Введите b: ");

std::cin >> b;

printf("Введите c: ");

std::cin >> c;

int res = calc(a, b, c);// вычисление выражения

if(error == 1){

printf("\nОшибка! Деление на ноль. ");}

else{

printf("\nРезультат на ассемблере: ");

printf("%d", res);// вывод результата вычисления выражения

printf("\n\nРезультат на C++: ");

printf("%d", ((-2*c + b*82)/(a/4 - 1)));

}

printf("\n");

system("PAUSE");

return 0;

}

1.5 Ответ

На рисунке 1.2 приведено выполнение программы при вводе верных исходных параметров.

На рисунке 1.3 приведено выполнение программы в случае, когда делитель равен 0, то есть – при вводе некорректных данных. Программа выполняет проверку данного значения и выдает сообщение: «Ошибка! Деление на ноль».

Рисунок 1.2 − Работа программы в случае верного ввода исходных данных

Рисунок 1.3 − Работа программы в случае ввода некорректных значений

Лабораторная работа 2 «Арифметические команды и команды переходов в ассемблере»

2.1 Теоретические основы лабораторной работы

Команды, использованные в программе, приведены в таблице 2.1.

Таблица 2.1  Описание команд

Команда

Назначение

ADD

Сложение байтов или слов, содержащих двоичные данные.

SUB

Вычитание байтов или слов, содержащих двоичные данные.

IMUL

Выполняет операцию умножения для знаковых данных.

IDIV

Выполняет операцию деления для знаковых данных.

DEC

Уменьшает значение операнда в памяти или регистре на 1.

CDQ

Расширяет двойное слово со знаком до размера учетверенного слова (64 бита) со знаком. Используется для подготовки к операции деления, для которой размер делимого должен быть в два раза больше размера делителя.

OR

Операция логического ИЛИ над битами операнда назначения.

CMP

Сравнивает два операнда.

JE

Инструкция условного перехода «перейти, если равно».

JG

Инструкция условного перехода «перейти, если больше чем…»

JL

Инструкция условного перехода «перейти, если меньше чем…»

JO

Инструкция условного перехода «перейти по переполнению».

JMP

Используется в программе для организации безусловного перехода.

NOP

Используется для передачи управления при конвейерной организации вычислительного процесса.

MOV

Команда пересылки данных (из источника в приемник).

PUSH

Перемещает данные в стек.

POP

Считывает данные из стека.

Использованные в программе регистры приведены в таблице 2.2.

Таблица 2.2  Описание регистров

Регистр

Назначение

EAX

Регистр общего назначения. Аккумулятор.

EBX

Регистр общего назначения. База.

ECX

Регистр общего назначения. Счетчик.

EDX

Регистр общего назначения. Регистр данных.

Использованные библиотеки приведены в таблице 2.3.

Таблица 2.3  Описание библиотек

Библиотека

Назначение

"stdafx.h"

Служит для генерации файла предкомпилированных заголовков; в него включено большинство стандартных и используемых в каждом приложении включаемых файлов. Сделано это для того, чтобы ускорить компиляцию проекта.

<stdio.h>

Используется для организации стандартного ввода/вывода.

<iostream>

Используется для организации потокового ввода/вывода.

<locale.h>

Используется для смены кодировки.

2.2 Задание

  1. В программе необходимо реализовать функцию вычисления заданного условного целочисленного выражения, используя команды сравнения, условного и безусловного переходов на встроенном ассемблере.

  1. Результат X – целочисленный, возвращается из функции регистра eax.

  2. Значения переменных передаются в качестве параметров функции.

  3. В программе реализовать вывод результата на экран.

  4. Все параметры функции 32 битные числа.

  5. Проверку деления на 0 реализовать также на встроенном ассемблере.

  6. В качестве комментария к каждой строке необходимо указать, какой промежуточный результат, в каком регистре формируется.

  7. По возможности использовать команды сдвига.

2.3 Схема алгоритма

На рисунке 2.1 приведена схема алгоритма вычисления функции

Для того чтобы вычислить результат необходимо организовать ввод с клавиатуры исходных данных (параметров a, b). После ввода сравниваются значения введенных параметров. Если a>b, то результат есть значение функции (b/a+5), если a<b, то результат есть значение функции ((a*a-b)/b), иначе результат равен -5.

Рисунок 2.1 – Схема алгоритма вычисления исходного выражения

2.4 Решение

#include "stdafx.h"

#include <stdio.h> // стандартный ввод/вывод

#include <iostream> // потоковый ввод/вывод

// функция вычисления выражения ((b/a)+5 [a>b]; -5 [a=b]; (a*a-b)/b [a<b]);

bool error = 0;

int calc(int a, int b)

{

int result = 0;

__asm{

mov eax, -5 ; <eax> = -5;

mov ecx, a ; <ecx>=a

mov ebx, b ; <ebx>=b

cmp ecx, ebx ; сравнение a и b

jg l_bigger ; переход если a>b

jl l_smaller ; переход если a<b

mov result, eax ; result = eax

jmp end_1 ; переход на конец программы

l_bigger:

or ecx, ecx ; сравнение a и 0

je error1 ; ошибка деление на ноль

mov eax, ebx ; <eax>=b

cdq ; подготовка деления <edx:eax> = a

idiv ecx ; <eax> = b/a

add eax, 5 ; <eax> = b/a + 5

mov result, eax ; result = eax

jmp end_1 ; переход на конец программы

l_smaller:

or ebx, ebx ; сравнение b и 0

je error1 ; ошибка деление на ноль

mov eax, ecx ; <eax>=a

imul ecx ; <edx:eax> = a*a

jo error1 ; ошибка переполнение

sub eax, ebx ; <eax> = a*a – b

cdq ; подготовка деления <edx:eax>

idiv ebx ; < eax> = (a*a – b)/b

mov result, eax ; result = eax

jmp end_1 ; переход на конец программы

error1:

mov error, 1

end_1:

}

return result ; // возвращение результата

}

int ccalc(int a, int b) //[a>b] (b/a)+5; [a=b] -5; [a<b] (a*a-b)/b

{

if(a>b){

return ((b/a)+5);

}

else{

if(a<b){

return ((a*a-b)/b);

}

else{

return (-5);

}

}

}

int _tmain(int argc, _TCHAR* argv[])

{

setlocale(LC_CTYPE,"rus");

printf("Лабораторная работа№2\n");

printf("Вариант: 3\n");

printf("Автор: Галанова Дарья\n");

printf("Группа: 6113\n");

printf("Задание:\n");

printf("Вычисление выражения с условием:\n\n [a>b]\t(b/a)+5;\n [a=b]\t-5;\n [a<b]\t(a*a-b)/b\n\n");

int a, b;

printf("Введите a: ");// стандартный вывод

std::cin >> a;// потоковый ввод

printf("Введите b: ");

std::cin >> b;

int res = calc(a, b);// вычисление выражения

if(error == 1){

std::cout<<"Ошибка"<<std::endl;

}

else{

printf("\nРезультат на ассемблере: ");

printf("%d", res);// вывод результата вычисления выражения

printf("\n\nРезультат на C++: ");

printf("%d", ccalc(a,b));

}

printf("\n");// стандартный вывод

system("PAUSE");

return 0;

}

2.5 Ответ

На рисунках 2.2, 2.3, 2.4 приведены тестовые примеры выполнения программы при вводе корректных исходных данных. На рисунке 2.5 приведен результат работы программы в случае ввода недопустимых значений, когда делитель равен 0. Программа выполняет проверку данного значения и выдает предупредительное сообщение.

Рисунок 2.2 − Работа программы в случае a>b

Рисунок 2.3 − Работа программы в случае a=b

Рисунок 2.4 − Работа программы в случае a<b

Рисунок 2.5 − Работа программы в случае некорректного ввода данных

Лабораторная работа 3 «Команды работы с массивами и стеком»

3.1 Теоретические основы лабораторной работы

Команды, использованные в программе, приведены в таблице 3.1.

Таблица 3.1  Описание команд

Команда

Назначение

INC

Увеличивает значение операнда в памяти или регистре на 1.

CMP

Сравнивает два операнда.

JNE

Инструкция условного перехода «перейти, если не равно».

JCXZ

Инструкция перехода внутри текущего сегмента команд в зависимости от некоторого условия.

LOOP

Используется для организации цикла со счетчиком в регистре ECX.

JMP

Используется в программе для организации безусловного перехода.

MOV

Команда пересылки данных (из источника в приемник).

XOR

Операция логического исключающего ИЛИ над двумя операндами размерностью байт, слово или двойное слово (побитовое сравнение).

Использованные в программе регистры приведены в таблице 3.2.

Таблица 3.2  Описание регистров

Регистр

Назначение

EAX

Регистр общего назначения. Аккумулятор.

EBX

Регистр общего назначения. База.

ECX

Регистр общего назначения. Счетчик.

EDX

Регистр общего назначения. Регистр данных.

ESI

Регистр общего назначения. Индекс источника.

Использованные библиотеки приведены в таблице 3.3.

Таблица 3.3  Описание библиотек

Библиотека

Назначение

"stdafx.h"

Служит для генерации файла предкомпилированных заголовков.

<stdio.h>

Используется для организации стандартного ввода/вывода.

<iostream>

Используется для организации потокового ввода/вывода.

<locale.h>

Используется для смены кодировки.

3.2 Задание

  1. В программе необходимо реализовать функцию обработки элементов массива используя команды сравнения, переходов и циклов на встроенном ассемблере.

  2. Результат целочисленный, возвращается из функции в регистре eax.

  3. Массив передаётся в качестве параметра функции.

  4. В программе реализовать вывод результата на экран.

  5. В качестве комментария к каждой строке необходимо указать, какое действие выполняет команда относительно массива.

Найти количество элементов массива A={a[i]}, которые удовлетворяют условию: a[i] = 0.

3.3 Схема алгоритма

На рисунке 3.1 приведена схема алгоритма поиска нулевых элементов массива A. Для этого организовывается ввод с клавиатуры длины массива (size). Затем поэлементно заполняется массив (mas[ ]). Каждый i-тый элемент сравнивается с 0. Если элемент равен 0, то значение счетчика увеличивается на единицу, иначе цикл переходит к следующему элементу (i + 1). В качестве результата на экран выводится значение счетчика.

Рисунок 3.1 – Схема алгоритма подсчета нулевых элементов массива

3.4 Решение

#include "stdafx.h"

#include <stdio.h> // стандартный ввод/вывод

#include <iostream> // потоковый ввод/вывод

#include <locale.h>

// В одномерном массиве A={a[i]} целых чисел вычислить количество нулевых элементов;

int massiv(int mas[], int razmer)

{

int result = 0;

__asm{

xor esi , esi ; подготовим регистр индекса в массиве

xor edi , edi ; счётчик количества элементов

mov ebx , mas ; ebx указывает на начало массива

mov ecx , razmer ; счётчик цикла по всем элементам массива

mov edx , 0 ; подготовка для сравнения с 0

jcxz exit_1 ; завершить если длина массива 0

begin_loop:

mov eax , [ebx + esi*4] ; определяем текущий элемент

cmp eax , edx ; равнение mas[i] и 0

jne end_loop ; если не равно нулю, то конец цикла

inc edi ; элемент удовлетворяет условию, увеличиваем счётчик

end_loop:

inc esi ; переходим к следующему элементу

loop begin_loop ; повторяем цикл для всех элементов массива

exit_1: mov result , edi ; возвращаем количество элементов

}

return result ; // возвращаем результат вычисления выражения

}

int cmassiv(int mas[], int razmer)

{

int k = 0;

for (int j=0; j<razmer; j++)

{

if(mas[j] == 0) k++;

}

return (k);

}

int _tmain(int argc, _TCHAR* argv[])

{

setlocale(LC_CTYPE,"rus");

printf("Лабораторная работа№3\n");

printf("Вариант: 3\n");

printf("Автор: Галанова Дарья\n");

printf("Группа: 6113\n");

printf("Задание:\n");

printf("В одномерном массиве целых чисел вычислить количество нулевых элементов\n\n");

int size;

do{

std::cout << "Введите размер массива не больше 50: " << std::endl;// потоковый вывод

std::cin >> size;// потоковый ввод

}while(size>50|| size<0);

printf("\nВведите массив: \n");// стандартный вывод

int mas[50];

for (int i = 0; i< size; i++) // цикл для ввода массива

{

std::cin>>mas[i];// потоковый ввод

}

int res = massiv(mas, size);// вычисление выражения

printf("\n\nКоличество нулей: ");// стандартный вывод

printf("\nАссемблер: ");

printf("%d", res);// вывод результата вычисления выражения

printf("\nC++: ");

printf("%d", cmassiv(mas,size));

printf("\n");// стандартный вывод

system("PAUSE");

return 0;

}

3.5 Ответ

На рисунке 3.2 приведен тестовый пример выполнения программы при вводе корректных данных. На рисунке 3.3 приведен результат работы программы в случае ввода недопустимых значений (например, ввод отрицательной длины массива). Программа выполняет проверку на корректность и выдает предупредительное сообщение.

Рисунок 2.2 − Работа программы в случае корректного ввода длины массива

Рисунок 2.3 − Работа программы при попытке ввода некорректной длины массива

Лабораторная работа 4 «Изучение работы математического сопроцессора в среде Assembler»

4.1 Теоретические основы лабораторной работы

Команды, использованные в программе, приведены в таблице 4.1.

Таблица 4.1  Описание команд

Команда

Назначение

FINIT

Инструкция инициализации сопроцессора.

FSTSW

Сохраняет текущее значение регистра SR в приемник.

SAHF

Загружает флаги из регистра AH.

FTST

Сравнивает текущее значение с нулем.

FLD

Загружает из памяти в вершину стека вещественное число.

FILD

Загружает из памяти в вершину стека ST(0) целое число.

FSTP

Извлекает из вершины стека ST(0) в память вещественное число.

FADDP

Сложение с «выбросом» результата в стек.

FSUBP

Вычитание с «выбросом» результата в стек.

FMUL

Умножение.

FMULP

Умножение с «выбросом» результата в стек.

FDIV

Деление.

FDIVP

Деление с «выбросом» результата в стек.

JA

Инструкция условного перехода «перейти, если больше чем…»

JB

Инструкция условного перехода «перейти, если меньше чем…»

JE

Инструкция условного перехода «перейти, если равно».

JMP

Используется в программе для организации безусловного перехода.

MOV

Команда пересылки данных (из источника в приемник).

FCOM

Сравнивает два операнда.

FLDZ

Поместить в стек +0,0

Использованные в программе библиотеки приведены в таблице 4.2.

Таблица 4.2  Описание библиотек

Библиотека

Назначение

"stdafx.h"

Служит для генерации файла предкомпилированных заголовков; в него включено большинство стандартных и используемых в каждом приложении включаемых файлов. Сделано это для того, чтобы ускорить компиляцию проекта.

<stdio.h>

Используется для организации стандартного ввода/вывода.

<iostream>

Используется для организации потокового ввода/вывода.

<locale.h>

Используется для смены кодировки.

4.2 Задание

  1. В программе необходимо реализовать функцию вычисления заданного условного выражения на языке ассемблера с использованием команд арифметического сопроцессора.

  1. Значения переменных передаются в качестве параметров функции.

  2. В программе реализовать вывод результата на экран.

  3. Все параметры функции имеют тип double.

  4. Проверку деления на 0 реализовать также на встроенном ассемблере.

  5. В качестве комментария к каждой строке необходимо указать, какой промежуточный результат, в каком регистре формируется.

  6. В качестве комментария к строкам, содержащим команды сопроцессора необходимо указать состояние регистров сопроцессора.

  7. Результат можно возвращать из функции в вершине стека сопроцессора.

4.3 Схема алгоритма

Рисунок 4.1 – Схема алгоритма вычисления исходного выражения

На рисунке 4.1 приведена схема алгоритма вычисления функции

Для того чтобы вычислить результат необходимо организовать ввод с клавиатуры исходных данных (параметров a, b). После ввода сравниваются значения введенных параметров. Если a>b, то результат есть значение функции (b/a+5), если a<b, то результат есть значение функции ((a*a-b)/b), иначе результат равен -5.

4.4 Решение

#include "stdafx.h"

#include <stdio.h> // стандартный ввод/вывод

#include <iostream> // потоковый ввод/вывод

#include <locale.h>

// функция вычисления выражения ((b/a)+5 [a>b]; -5 [a=b]; (a*a-b)/b [a<b]);

bool error = 0;

double func(double a, double b)

{

double res; int status; const int c5=-5;

__asm{

finit ; инициализация сопроцессора

fld qword ptr[b] ; b

fld qword ptr[a] ; a b

fcom st(1) ; сравниваем a и b

fstsw status ; сохраняем регистр флагов сопроцессора

mov ah, byte ptr [status+1]

sahf ; записываем в регистр флагов процессора

ja a_bigger ; переход если a больше

jb b_bigger ; переход если b больше

; если равны

fild c5 ; -5 a b

jmp endcalc

a_bigger: ftst ; сравнение a с 0

fstsw status ; сохраняем регистр флагов сопроцессора

mov ah, byte ptr [status+1]

sahf ; записываем в регистр флагов процессора

je err ; переход если a=0

fdivp st(1), st ; b/a

fild c5 ; 5 b/a

fsubp st(1), st ; b/a+5

jmp endcalc

b_bigger: fldz ; 0 a b

fcomp st(2) ; сравнение b с 0

; a b

fstsw status ; сохраняем регистр флагов сопроцессора

mov ah, byte ptr [status+1]

sahf ; записываем в регистр флагов процессора

je err ; переход если b=0

fld st ; a a b

fmulp st(1), st ; a a*a b

fld st(1) ; b a*a b

fsubp st(1), st ; a*a-b b

fdivrp st(1), st ; (a*a-b)/b

jmp endcalc

err: mov error, 1 ; ввод ошибки

endcalc: fstp res ; сохранение результата

}

return res;

}

int _tmain(int argc, _TCHAR* argv[])

{

setlocale(LC_CTYPE,"rus");

printf("Лабораторная работа№4\n");

printf("Вариант: 3\n");

printf("Автор: Галанова Дарья\n");

printf("Группа: 6113\n");

printf("Задание:\n");

printf("Вычисление выражения с помощью сопроцессора.\n Условие:\n\n [a>b]\t(b/a)+5;\n [a=b]\t-5;\n [a<b]\t(a*a-b)/b\n\n");

double a, b;

printf("Введите a: \n");// стандартный вывод

std::cin >> a;// потоковый ввод

printf("Введите b: \n");// стандартный вывод

std::cin >> b;// потоковый ввод

double res = func(a, b);// вычисление выражения

if(error != 1)

{

if(a>b)

{

std::cout<<"\nРезультат С++ : [a>b] \t "<< (b/a)+5 << std::endl;

}

else{

if(a<b){

std::cout<<"\nРезультат С++ : [a<b] \t "<< (a*a-b)/b << std::endl;

}

else{

std::cout<<"\nРезультат С++ : [a=b] \t "<< -5 << std::endl;

}

}

std::cout<<"\nРезультат на ассемблере: "<< res << std::endl;

}

else{

std::cout<<"\nОшибка!"<<std::endl;

}

system("PAUSE");

return 0;

}

4.5 Ответ

На рисунках 4.2, 4.3, 4.4 приведены тестовые примеры выполнения программы при вводе корректных исходных данных. На рисунке 4.5 приведен результат работы программы в случае ввода недопустимых значений, когда делитель равен 0. Программа выполняет проверку данного значения и выдает предупредительное сообщение.

Рисунок 4.2 − Работа программы в случае a>b

Рисунок 4.3 − Работа программы в случае a=b

Рисунок 4.4 − Работа программы в случае a<b

Рисунок 4.5 − Работа программы в случае некорректного ввода данных

Лабораторная работа 5 «Команды нахождения тригонометрических функций с помощью математического сопроцессора»

5.1 Теоретические основы лабораторной работы

Команды, использованные в программе, приведены в таблице 5.1.

Таблица 5.1  Описание команд

Команда

Назначение

FINIT

Инструкция инициализации сопроцессора.

FLD

Загружает из памяти в вершину стека ST(0) вещественное число.

FSIN

Вычисление значения синуса ST(0).

FSUBP

Вычитание с «выбросом» результата в стек.

Использованные в программе библиотеки приведены в таблице 5.2.

Таблица 5.2  Описание библиотек

Библиотека

Назначение

"stdafx.h"

Служит для генерации файла предкомпилированных заголовков; в него включено большинство стандартных и используемых в каждом приложении включаемых файлов. Сделано это для того, чтобы ускорить компиляцию проекта.

<stdio.h>

Используется для организации стандартного ввода/вывода.

<iostream>

Используется для организации потокового ввода/вывода.

<locale.h>

Используется для смены кодировки.

5.2 Задание

  1. В программе необходимо реализовать функцию f(x)=xsinx, зависящую от аргумента x на языке ассемблера с использованием команд арифметического сопроцессора.

  2. Значения переменных передаются в качестве параметров функции.

  3. Составить таблицу значений функции на отрезке [π, π] с шагом h=0,1.

  4. Номер вычисления , значения x и f(x) вывести на экран.

  5. Все параметры функции имеют тип double.

  6. В качестве комментария к каждой строке необходимо указать, какой промежуточный результат, в каком регистре формируется.

  7. В качестве комментария к строкам, содержащим команды сопроцессора необходимо указать состояние регистров сопроцессора.

  8. Результат можно возвращать из функции в вершине стека сопроцессора.

5.3 Схема алгоритма

На рисунке 5.1 приведена схема алгоритма вычисления функции y=xsinx. Значение параметра x поступает из цикла основной программы. Далее производится пошаговое вычисление значения выражения.

Рисунок 5.1 – Схема алгоритма вычисления выражения y=xsinx.

5.4 Решение

#include "stdafx.h"

#include <stdio.h>

#include <iostream>

#include <locale.h>

#include <math.h>

#define PI 3.14159265

double funcasm(double x)

{

_asm

{

finit;

fld x ;x

fld st ;x x

fsin ;sinx x

fsubp st(1), st ;x - sinx

}

}

double funccpp(double x)

{

return(x - sin(x));

}

int _tmain(int argc, _TCHAR* argv[])

{

setlocale(LC_ALL,"RUSSIAN");

printf("Лабораторная работа№5");

printf("Вариант: 3");

printf("Автор: Галанова Дарья");

printf("Группа: 6113");

printf("\n");

printf("Задание:");

printf("\n");

printf("Функция:y = x - sin(x)\nОтрезок:[-pi,pi]\nШаг:0,1");

printf("\n");

printf("\t\t\t\tТАБЛИЦА ОТВЕТОВ");

printf("\n");

printf("\n");

double h =0.1;

int i = 0;

double x = -PI;

printf("==================================================================\n");

std::cout<<" "<<" № "<<"\t\t"<<" x "<<"\t\t"<<" АССЕМБЛЕР"<<"\t\t"<<"C++";

printf("\n");

printf("==================================================================\n");

while((x >= -PI)&&(x <= PI))

{

printf(" %d \t\t% 0.1f \t\t % 0.4f \t\t% 0.4f",i + 1,x,funcasm(x),funccpp(x));

printf("\n");

x += h;

i++;

}

printf("\n");

printf("==================================================================\n\n\n");

system("PAUSE");

return 0;

}

5.5 Ответ

На рисунках 5.2, 5.3 приведен тестовый пример работы программы.

Рисунок 5.2 − Работа программы (вывод до 48 строки)

Рисунок 5.3 − Работа программы (вывод от 49 до 63 строки)

Лабораторная работа 6 «Нахождение суммы ряда с помощью математического сопроцессора»

6.1 Теоретические основы лабораторной работы

Команды, использованные в программе, приведены в таблице 6.1.

Таблица 6.1  Описание команд

Команда

Назначение

FINIT

Инструкция инициализации сопроцессора.

FSTSW

Сохраняет текущее значение регистра SR в приемник.

SAHF

Загружает флаги из регистра AH.

FLD

Загружает из памяти в вершину стека ST(0) вещественное число.

FLDZ

Поместить в стек +0,0

FILD

Загружает из памяти в вершину стека ST(0) целое число.

FSTP

Извлекает из вершины стека ST(0) в память вещественное число.

FADDP

Сложение с «выбросом» результата в стек.

FMUL

Умножение.

FMULP

Умножение с «выбросом» результата в стек.

FDIVP

Деление с «выбросом» результата в стек.

FSIN

Вычисление значения синуса ST(0).

FXCH

Обмен содержимым верхушки стека и численного регистра указанного в качестве оператора команды.

FCOM

Сравнивает два операнда.

JL

Инструкция условного перехода «перейти, если меньше чем».

JG

Инструкция условного перехода «перейти, если больше чем…»

INC

Увеличивает значение операнда в памяти или регистре на 1.

MOV

Команда пересылки данных (из источника в приемник).

CMP

Сравнивает два операнда.

Использованные в программе библиотеки приведены в таблице 6.2.

Таблица 6.2  Описание библиотек

Библиотека

Назначение

"stdafx.h"

Служит для генерации файла предкомпилированных заголовков.

<stdio.h>

Используется для организации стандартного ввода/вывода.

<iostream>

Используется для организации потокового ввода/вывода.

<locale.h>

Используется для смены кодировки.

6.2 Задание

  1. В программе необходимо реализовать функцию определения значения функции , зависящей от аргумента x на языке ассемблера с использованием команд арифметического сопроцессора.

  2. Функция вычисляется в виде суммы ряда: Вычисления прекращаются, если , где – последующий член ряда; - предыдущий член ряда. Кроме того, на случай плохой сходимости следует ограничить количество слагаемых сверху некоторым наперёд заданным , т.е. выход их вычислительной процедуры может произойти не по условию , а по условию . Значение функции и количество итераций вывести для контроля на экран.

  3. Значение параметров x, ε и N передаются в качестве аргументов.

  4. В программе необходимо также реализовать функцию вычисления значения элементарной функции на основе аналитического выражения, также с использованием команд арифметического сопроцессора. Значение функции вывести для контроля на экран.

  5. Необходимо определить достигнутую погрешность, вычислив отклонение аналитического значения от вычисленного значения.

  6. В качестве комментария к строкам содержащим команды сопроцессора необходимо указать состояние регистров сопроцессора.

6.3 Схема алгоритма

На рисунке 6.1 приведена схема алгоритма вычисления значения функции . Для того чтобы вычислить результат, необходимо организовать ввод с клавиатуры исходных данных (x, N, eps). Запускается цикл разложения в ряд : нахождение выражений (2k+1), sin(2k+1) и их частного, которое затем умножается на x. Условием выхода из цикла является превышение заданной погрешности текущего члена ряда, или превышение заранее заданного числа шагов(N) количеством итераций цикла. Результатом работы программы является значение суммы элементов.

Рисунок 6.1 – Схема алгоритма разложения в ряд

6.4 Решение

#include "stdafx.h"

#include <iostream>

#include <stdio.h>

#include <locale.h>

#include <math.h>

#define M_PI_4 0.785398163

double funcasm(double x, double eps, int N)

{

int status;int counter = -1; double otvet = 0;int const c2 =2; int const c1 =1;

_asm

{

mov ecx,N ; инициализация счётчика

finit ; инициализация сопроцессора

fld qword ptr[eps] ; eps

fld qword ptr[x] ; x eps

fldz ; sum=0 x eps

calc:

inc counter ; k++

fild counter ; k sum x eps

fild c2 ; 2 k sum x eps

fmulp st(1),st ; 2k sum x eps

fild c1 ; 1 2k sum x eps

faddp st(1), st ; 2k+1 sum x eps

fld st ; 2k+1 2k+1 sum x eps

fsin ;sin(2k+1) 2k+1 sum x eps

fxch st(1) ; 2k+1 sin(2k+1) sum x eps

fdivp st(1), st ;sin(2k+1)/2k+1 sum x eps

fmul st, st(2) ;xsin{2k+1)/2k+1 sum x eps

fcom st(4) ; сравниваем погрешность с текущим членом ряда

fstsw status ; сохраняем регистр флагов сопроцессора

mov ah, byte ptr [status+1]

sahf ; записываем в регистр флагов процессора

jl endcalc ; переход на конец, если достигли погрешность

faddp st(1),st ; sum+s x eps

cmp ecx, counter ; сравниваем достижение количества членов

jg calc ; переход на начало

endcalc:

fstp otvet ; сохранение результата sum

}

N = counter;

return otvet;

}

double analitic(double x)

{

double c4 = M_PI_4;

__asm{

finit ; подключение сопроцесора

fld x ; x

fld c4 ; pi/4 x

fmul st, st(1) ; pi/4 * x

}

}

double funccpp(double x)

{

return M_PI_4*x;

}

int _tmain(int argc, _TCHAR* argv[])

{

setlocale(LC_ALL,"RUSSIAN");

printf("Лабораторная работа№6\n");

printf("Вариант: 3\n");

printf("Автор: Галанова Дарья\n");

printf("Группа: 6113\n");

printf("Задание:\nОпределение значения _pi/4 * x_\n\n");

double x;

double eps;

int N;

printf("\t\t\tВВОД ДАННЫХ\n\n");

double m = 0;

double n = 1;

printf("Введите значние _x_, принадлежащее промежутку [%f;%f],\nкол-во итераций и погрешность: \n\n",m,n);

do{

std::cout<<"Введите x: ";

std::cin >> x;

}while((x < m) || (x > n));

printf("\n");

do{

printf("Введите количество итераций: ");

std::cin >> N;

}while (N<1);

printf("\n");

do{

printf("Введите погрешность: ");

std::cin >> eps;

}while (eps>1 || eps <0);

printf("\n\n\n\t\t\tТАБЛИЦА ОТВЕТОВ\n\n");

printf("======================================================================\n");

std::cout<<" x "<<"\t"<<" АССЕМБЛЕР "<<"\t"<<" АССЕМБЛЕР2"<<"\t"<<" C++""\t"<<"ПОГРЕШНОСТЬ\n";

printf("======================================================================\n");

printf("% 0.3f \t% 0.7f \t% 0.7f \t% 0.7f \t% 0.7f",x,funcasm(x,eps,N),analitic(x),funccpp(x), abs(funcasm(x,eps,N)- analitic(x)));

printf("\n======================================================================\n\n");

system("PAUSE");

return 0;

}

6.5 Ответ

На рисунке 6.2 приведены тестовые примеры выполнения программы при вводе корректных исходных данных. На рисунке 6.3 приведен результат работы программы в случае попыток ввода некорректных значений. Программа выполняет проверку вводимых значений и дает шанс исправить некорректный параметр.

Рисунок 6.2 − Работа программы в случае верного ввода исходных данных

Рисунок 6.3 − Работа программы при попытке ввода некорректных данных

Список использованных источников

  1. Зеленко, Л.С. Методические указания к лабораторной работе № 1 «Арифметические и логические команды в ассемблере» [Текст]/ Л.С. Зеленко, Д.С. Оплачко. – Самара: изд-во СГАУ, 2015. – 24 с.

  2. Зеленко, Л.С.. Методические указания к лабораторной работе № 2 «Арифметические команды и операторы условного перехода» [Текст]/ Л.С. Зеленко, Д.С. Оплачко. – Самара: изд-во СГАУ, 2015. – 24 с.

  3. ГОСТ 19.701-90 (ИСО 5807-85). ЕСПД. Схемы алгоритмов, программ, данных и систем. Условные обозначения и правила выполнения [Текст] ‑ Введ. 1990-01-01. – М.: Изд-во стандартов, 1991.  26 с.

  4. Оплачко, Д.С. Методические указания к лабораторной работе № 3 «Работа с массивами и стеком на языке Assembler» [Текст]/ Д.С. Оплачко, Л.С. Зеленко. – Самара: изд-во СГАУ, 2012. – 19 с.

  5. Оплачко, Д.С. Методические указания к лабораторной работе № 4 «Работа с математическим сопроцессором в среде Assembler» [Текст]/ Д.С. Оплачко, Л.С. Зеленко. – Самара: изд-во СГАУ, 2012. – 19 с.

  6. СТО СГАУ 02068410-004-2007. Общие требования к учебным текстовым документам [Текст]: методические указания.  Самара: Изд-во Самар. гос. аэрокосм. ун-та, 2007.  30 с.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]