Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Консольные приложения для FPU

Поиск

Ввод-вывод и обработка вещественных чисел в консольных приложениях осуществляется в следующем порядке:

1. Консольный ввод чисел в виде текста с помощью api-функций ReadConsole

2. Преобразование текстовых данных в вещественные числа с помощью функции FpuAtoFL

3. Загрузка чисел в FPU

4. Выполнение вычислений

5. Выгрузка (сохранение) результатов в память

6. Преобразование вещественных чисел в текстовые данные с помощью функции FpuFLtoA

7. Консольный вывод результатов с помощью api-функций WriteConsole.

При малом количестве исходных данных парные операции 2, 3 и 5, 6 могут объединяться.

Пример 1.7.6. Программа демонстрирует ввод двух чисел с клавиатуры, вычисление их произведения и вывод вещественного результата в консольное окно. Операции преобразования и загрузки, а также операции выгрузки и преобразования объединены. Размер каждого слагаемого ограничен шестью символами, включая десятичную запятую. В связи с тем, что для функции преобразования строки в число требуется строка, заканчивающаяся нулём, а консольный ввод добавляет в конце вводимой строки коды 0D и 0A, то в программе байт 0D затирается нулями.

.data

X Byte 8 Dup (0); первое слагаемое + коды 0D,0A (Enter)

Y Byte 8 Dup (0); второе слагаемое + коды 0D,0A (Enter)

R Byte 16 Dup (0); произведение

outHandle DWORD 0

bytesWritten DWORD 0

inHandle DWORD 0

bytesRead DWORD 0

.code

start:

INVOKE GetStdHandle, STD_INPUT_HANDLE

mov inHandle,eax

INVOKE ReadConsole, inHandle, offset X, 8, offset bytesRead, 0

mov edi,bytesRead

mov X[edi-2],0; строка X – завершается нулём

INVOKE ReadConsole, inHandle, offset Y, 8, offset bytesRead, 0

mov edi,bytesRead

mov Y[edi-2],0; строка Y – завершается нулём

INVOKE FpuAtoFL, ADDR X, 0, DEST_FPU

INVOKE FpuAtoFL, ADDR Y, 0, DEST_FPU

fmul

INVOKE FpuFLtoA, 0, 6, ADDR R, SRC1_FPU or SRC2_DIMM

INVOKE GetStdHandle, STD_OUTPUT_HANDLE

mov outHandle,eax

INVOKE WriteConsole, outHandle, offset R, 16, offset bytesWritten, 0

INVOKE ReadConsole, inHandle, offset X, 1, offset bytesRead, 0

invoke ExitProcess, 0

end start

Упражнение 1.7.2. На основе примера 1.7.6 разработать программу деления X/Y. Размер каждого числа равен 10 байт. Количество знаков после запятой в результате деления равно 12.

Вычисление выражений в FPU

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

Пример 1.7.7. Консольная программа демонстрирует вычисление выражения 1+(X–Y)/Z. Числа X, Y и Z вводятся с клавиатуры в указанном порядке. Вначале необходимо вычесть Y из X, затем разделить на Z, потом полученный результат сложить с единицей.

.data

X Byte 8 Dup (0); первое вводимое число

Y Byte 8 Dup (0); второе вводимое число

Z Byte 8 Dup (0); третье вводимое число

R Byte 16 Dup (0); результат

outHandle DWORD 0

bytesWritten DWORD 0

inHandle DWORD 0

bytesRead DWORD 0

.code

start:

INVOKE GetStdHandle, STD_INPUT_HANDLE

mov inHandle,eax

INVOKE ReadConsole, inHandle, offset X, 8, offset bytesRead, 0

mov edi,bytesRead

mov X[edi-2],0

INVOKE ReadConsole, inHandle, offset Y, 8, offset bytesRead, 0

mov edi,bytesRead

mov Y[edi-2],0

INVOKE ReadConsole, inHandle, offset Z, 8, offset bytesRead, 0

mov edi,bytesRead

mov Z[edi-2],0

INVOKE FpuAtoFL, ADDR X, 0, DEST_FPU; st(0)=X

INVOKE FpuAtoFL, ADDR Y, 0, DEST_FPU; st(0)=Y, st(0)=Y

Fsub; st(0)=X-Y

INVOKE FpuAtoFL, ADDR Z, 0, DEST_FPU; st(1)=X-Y, st(0)=Z

Fdiv; st(0)=(X-Y)/Z

fld1; st(0)=1, st(1)=(X-Y)/Z

fadd; st(0)=1+(X-Y)/Z

INVOKE FpuFLtoA, 0, 6, ADDR R, SRC1_FPU or SRC2_DIMM

INVOKE GetStdHandle, STD_OUTPUT_HANDLE

mov outHandle,eax

INVOKE WriteConsole, outHandle, offset R, 16, offset bytesWritten, 0

INVOKE ReadConsole, inHandle, offset X, 1, offset bytesRead, 0

invoke ExitProcess, 0

end start

Упражнение 1.7.3. Разработать программу для вычисления выражения: 2*Sin(X)*Cos(X) – loge(2). Подсказка: воспользуйтесь встроенными функциями FPU, описанными в Приложении В.

Упражнение 1.7.4. Разработать программу для вычисления выражения: X*log2(Y+1)+|X-Y|. Подсказка: воспользуйтесь встроенными функциями FPU, описанными в Приложении В.

Условные вычисления

Для организации условных вычислений сравнение чисел выполняется в FPU, после чего содержимое регистра состояния (SW) копируется в AX или в память.

Пример 1.7.8. Пусть необходимо найти значение переменной X по следующему правилу:

Переменные Y и Z вводятся с клавиатуры. В случае попытки сравнения несравнимых величин программа выводит сообщение об ошибке (такая ситуация может возникнуть при вводе нечисловых данных).

.data

Y Byte 8 Dup (0); первое строковое число

Z Byte 8 Dup (0); второе строковое число

ZZ Real10?; второе вещественное число

X Byte 16 Dup (0); строковый результат

Err Byte "Compare Error",0; сообщение об ошибке

outHandle DWORD 0

bytesWritten DWORD 0

inHandle DWORD 0

bytesRead DWORD 0

.code

start:

INVOKE GetStdHandle, STD_INPUT_HANDLE

mov inHandle,eax

INVOKE GetStdHandle, STD_OUTPUT_HANDLE

mov outHandle,eax

INVOKE ReadConsole, inHandle, offset Y, 8, offset bytesRead, 0

mov edi,bytesRead

mov Y[edi-2],0

INVOKE ReadConsole, inHandle, offset Z, 8, offset bytesRead, 0

mov edi,bytesRead

mov Z[edi-2],0

INVOKE FpuAtoFL, ADDR Z, 0, DEST_FPU; st = Z

INVOKE FpuAtoFL, ADDR Y, 0, DEST_FPU; st = Y, st(1) = Z

FCOM; сравнение Y и Z

FSTSW AX; пересылка результата сравнения из SW в AX

mov al,ah; дублирование необходимых флагов в AL

and al,01000101b; выделение флагов C3,C2 и C0

cmp al,01000101b; тест ошибки сравнения

jz error_handler; если ошибка, то на error_handler

mov al,ah; дублирование необходимых флагов в AL

and al,01000000b; выделение флага C3

cmp al,01000000b; тест истинности условия Y=Z

jnz lower_greater; если неравно, то на lower_greater

FSIN; если равно, то st = Sin(st)

jmp print; на печать результата

lower_greater:

and ah,00000001b; выделение флага C0

cmp ah,00000001b; тест истинности условия Y<Z

jz lower; если меньше, то на lower

FXCH; иначе (Y>Z) обмен: st = Z, st(1) = Y

FCOS; st = Cos(st)

jmp print; на печать результата

lower:

fld1; st = 1.0, st(1) = Y, st(2) = Z

FXCH; st = Y, st(1) = 1.0, st(2) = Z

FYL2X; st = 1.0*log2(Y), st(1) = 1.0, st(2) = Z

print:

INVOKE FpuFLtoA, 0, 6, ADDR X, SRC1_FPU or SRC2_DIMM

INVOKE WriteConsole, outHandle, offset X, 16, offset bytesWritten, 0

jmp quit

error_handler:

INVOKE WriteConsole, outHandle, offset Err, 16, offset bytesWritten, 0

quit:

INVOKE ReadConsole, inHandle, offset X, 1, offset bytesRead, 0

invoke ExitProcess, 0

end start

Упражнение 1.7.5. Разработать программу определения максимального числа из трёх вводимых с клавиатуры вещественных чисел.

Упражнение 1.7.6. Разработать программу определения максимального по модулю числа из трёх чисел, вводимых с клавиатуры.



Поделиться:


Последнее изменение этой страницы: 2016-06-29; просмотров: 433; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 13.59.192.81 (0.007 с.)