Вы находитесь на странице: 1из 7

Семестровая работа Студент Цветков И. И.

Сложение и умножение чисел Группа ИВТ-260


повышеной точности
Дата выполнения
Проверил Кузнецов М.А.
Оценка

Цель: реализовать сложение и умножение чисел повышенной точности в виде функций


доступных из программ на языке Си. Числа повышенной точности представляются
массивами.

Функции:
Функция сложения чисел повышеной точности:
Числа хранятся от старшего байта к младшему
void addd(int *first,int *second,int *result,int size1,int size 2);
где:
first массив содержащий 1-е число повышеной точности
second массив содержащий 2-е число повышеной точности
result массив с результатом
size1 размер 1-го массива
size2 размер 2-го массива

Размер массива результата равен размеру самого длинного операнда.

Алгоритм:
1.скопировать длинный массив в массив результата
2.с учетом переноса складывать соответствующие эл-ты массива результата и короткого
массива, пока короткий массив не закончится, от концов массив к началам, массивы
считать выравнеными по концам.
3.оставшуюся часть массива результата с учетом переноса складывать с нулем.

Функция умножения чисел повышенной точности:


Числа хранятся от старшего байта к младшему
void mull(unsigned int *first, unsigned int *second, unsigned int *result, unsigned int size1,
unsigned int size 2);

first массив с 1-м числом


second массив со 2-м числом
result массив результата
size1 размер 1-го массива
size2 размер 2-го массива

Размер массива результата равен сумме размеров массивов операндов.

Алгоритм:
Перебор массивов производится от конца к началу, 1-м считается эл-т расположенным в
памяти последним, следующим считается эл-т расположенный в памяти перед текущим.
1. перебор первого массива до конца
1.1. сохранить текущий эл-т массива результата
1.2. перебор всех элементов второго массива
1.2.1 умножить текущий элемент первого массива на текущей элемент второго массива и
записать в текущей элемент результата
1.2.2.перейти к следующему эл-ту массива результатов
1.2.3.перейти к следующему эл-ту второго массива
1.3.вернуться к первому эл-ту второго массива
1.4.перейти к следующему эл-ту массива результата

Код на Ассемблере:
Умножение:
.386
ARR1 EQU [EBP+8] ;Адрес 1-го массива
ARR2 EQU [EBP+12];Адрес 2-го массива
RES EQU [EBP+16];Адрес массива с результатами
S1 EQU [EBP+20];Размер 1-го массива
S2 EQU [EBP+24];Размер 2-го массива
;числа хранятся в виде массивов т.к. многобитовые
public _lmul
.model flat
.code

_lmul PROC NEAR


;ВХОД
PUSH EBP
MOV EBP,ESP
;ТЕЛО

;Заполнение нулями массива результатов


MOV EDI,RES
MOV ECX,S1
ADD ECX,S2
XOR EAX,EAX
REP STOSD

;занести в регистры адреса последних элементов массивов


;arr1 - esi
;arr2 - edi
;res - ebx

MOV ESI, ARR1


MOV EDI, ARR2
MOV EAX, S1
DEC EAX
SHL EAX, 2
ADD ESI, EAX
MOV EBX, S2
DEC EBX
SHL EBX, 2

ADD EDI,EBX
ADD EBX,EAX
ADD EBX,RES
ADD EBX,4

;Сохранение размеров массивов


MOV EDX,S1
MOV ECX,S2

;Сохранение флажка переполнения и флажка направления


CMP EAX,EAX;
MOV SI, DI
STD
PUSHF
CYCLE1: ;Для каждого эл-та 2-го массива(от конца к началу) выполнить цикл2 сдвигаясь
каждый раз от конца массива результатов на 32

бита
POPF
PUSH ECX ;количество повторений внешнего цикла
PUSH EBX ;текущий адрес результат
PUSH ESI ;адрес последнего эл-та первого массива
PUSHF
MOV ECX,EDX

CYCLE2: ;Каждый эл-нт 1-го массива умножать на текущий эл-т 2-го массива и
записывать в массив результатов
LODSD ;взять эл-т из 1-го массива
MUL DWORD PTR [EDI];умножить на текущий эл-т 2-го массива
POPF
ADC [EBX],EAX;добавить к соответствующему эл-ту массива
результатов
ADC [EBX-4],EDX;добавить старшую часть после умножения
PUSHF
SUB EBX,4;перейти к следующему эл-ту массива результатов
LOOP CYCLE2
POPF
POP ESI ;адрес последнего элемента 1-го массива
PUSHF
CMP EBX,RES
JL E_N_D; учитывать возможность переноса при последнем
прохождении тела цикла
POPF
XOR EAX, EAX
ADC [EBX-4],EAX
PUSHF

E_N_D: POPF
POP EBX ;адрес с которого начинался внутренний цикл
PUSHF
SUB EBX,4 ;перейти к следующему эл-ту массива результатов
POPF
POP ECX ;кол-во повторений внешнего цикла
PUSHF
MOV EDX,S1;Внутренний цикл снова должен быть повторён для
каждого эл-та 1-го массива
SUB EDI,4;Перейти к следующему эл-ту 2-го массива
LOOP CYCLE1

JMP _EXIT
_EXIT: ;ВЫХОД
POP EBX
MOV ESP,EBP
POP EBP
RET
_lmul ENDP

END

Сложение:
.386
ARR1 EQU [EBP+8] ;Адрес 1-го массива
ARR2 EQU [EBP+12];Адрес 2-го массива
RES EQU [EBP+16];Адрес массива с результатами
S1 EQU [EBP+20];Размер 1-го массива
S2 EQU [EBP+24];Размер 2-го массива
;числа хранятся в виде массивов т.к. многобитовые

public _lad
.model flat
.code

_lad PROC NEAR


;ВХОД
PUSH EBP
MOV EBP,ESP
;ТЕЛО
PUSH EBX

MOV ECX,S1 ;в есх размер 1-го числа


MOV EDX,S2 ;в edx размер 2-го числа
CMP ECX,EDX
JGE NOXCHG ;Занесение в EDX размер большего массива в
ECX меньшего
XCHG ECX,EDX ;В ESI адрес большего массива, в EDI адрес
меньшего
MOV ESI,ARR2;
MOV EDI,ARR1;
JMP END_IF ;
NOXCHG: MOV ESI,ARR1;
MOV EDI,ARR2;

END_IF: PUSH ECX ;размер большего массива


PUSH EDI ;размер меньшего массива
MOV EDI,RES
REP MOVSD ;Скопировать больший массива в массив
результатов

MOV ECX,EDX ;размер меньшего массива


POP ESI ;адрес меньшего массива
MOV EDI,RES ;Адрес массива с результатами
POP EDX ;размер большего массива
PUSH ECX;размер меньшего массива

;Переводим индексные регистры на последнии элементы их массивов


MOV EAX,ECX
DEC EAX
SHL EAX, 2
ADD ESI, EAX
MOV EAX, EDX
DEC EAX
SHL EAX, 2
ADD EDI,EAX
;

; Правильная установка флажков


STD
MOV ES, DS
CMP EAX,EAX
PUSHF
CYCLE: ;считая индексы от конца массивов складывать эл-ты с одним индексом,
учитывая перенос от предыдущего сложения,
;результат сохранять в массиве результата, пока в более коротком массиве не
закончаться элементы
LODSD ;взять эл-т из короткого массива
MOV EBX,[EDI];взять эл-т из длинного массива(массива результатов)
POPF
ADC EAX,EBX;сложить их
PUSHF
STOSD ;сохранить в массив результатов(длинный массив)
LOOP CYCLE
;найти кол-во оставшихся эл-тов в длинном массиве
POPF
POP ECX
PUSHF
SUB EDX,ECX
MOV ECX,EDX
CYCLE2: ;оставшиеся эл-ты более длинного массива складывать с нулём, учитывая
перенос.
MOV EAX,[EDI] ;взять эл-т из длинного массива
POPF
ADC EAX,0 ;сложить с нулём учитывая перенос
PUSHF
STOSD
LOOP CYCLE2

POPF

MOV EAX,1 ;Вернуть правду


JMP _EXIT
ERR: XOR EAX,EAX ;Вернуть ложь
_EXIT: ;ВЫХОД

POP EBX
MOV ESP,EBP
POP EBP
RET
_lad ENDP
END

код на Си:
// ASMS.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <conio.h>
extern "C"
{
void addd(int *first,int *second,int *result,int size1,int size 2);
void mull(unsigned int *first, unsigned int *second, unsigned int *result, unsigned int size1,
unsigned int size 2);
}

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


{
int arr1[2]={0x0,0x10};
int arr2[4]={0x0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFF0F};
int res[4];
addd(arr1,arr2,res,2,4);
printf("%8X\n%8X\n%8X\n%8X\n",res[0],res[1],res[2],res[3]);
printf("*************************************************************\n");
unsigned int Arr1[2]={0x0,0x10};
unsigned int Arr2[3]={0xFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
unsigned int Res[5];
lmul(Arr1,Arr2,Res,2,3);
printf("%8X\n%8X\n%8X\n%8X\n%8X\n",Res[0],Res[1],Res[2],Res[3],Res[4]);
_getch();
return 0;
}