Форум программистов, компьютерный форум, киберфорум
Наши страницы

Assembler для начинающих

Войти
Регистрация
Восстановить пароль
 
 
fdrv
1 / 1 / 0
Регистрация: 11.02.2016
Сообщений: 20
#1

Вычисления значения функции в формате с плавающей запятой - Assembler

24.04.2016, 16:36. Просмотров 493. Ответов 20
Метки нет (Все метки)

Задание такое - Написать программу для решения функции y=х^2-x^4, где х меняется от -2 до +2 с шагом 0,5. Нужно вычислить функцию на каждом шаге. В формате вычисления с плавающей комой.
Процессор х86.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
TITLE Курсова робота
EXTERN MULFXX, MULFXY, ADDSUBFYZ, ADDSUBFYZ
 
STACK SEGMENT PARA STACKSTACK”
    DB  64 DUP (0)
STACK ENDS
 
DSEG SEGMENT PARA PUBLICDATA”
    X   DD  -2.0
        DX  DD    0.5
    Y   DD  1 DUP (0)
    Z   DD  1 DUP (0)
    R   DQ  8 DUP (0)
DSEG ENDS
 
CSEG SEGMENT PARA PUBLICCODE”
    ASSUME CS:CSEG, DS:DSEG, SS:STACK
 
MAIN PROC FAR
    mov ax,DSEG
    mov ds,ax
    mov cx,8  ; по скольку нужно сделать исчисления от -2 до +2 с шагом 0,5 заносим в счётчик(сх) 8
    push    cx  ; заносим в стек сх, по скольку в подпрограммах используется регистр сх
Start:  call    MULFXX  ; Возводим Х в квадрат и заносим результат в Y
    call    MULFYY  ; Возводим Х в 4 степень и заносим результат в Z
    call    ADDSUBFYZ  ; Y-Z
    pop cx  ; достаём сх из стека для цикла
    call    ADDSUBFXDX  ; для реализации шага выполняем эту подпрограмму, то есть x-dx, то есть 2.0-0,5, то есть, если сначала в Х было значение -2.0, то теперь там -1.5
    loop    Start  ; цикл
Такие вопросы
Как после выполнения всех подпрограмм занести результат со смещением 4 байта и в какой регистр его лучше занести ?
Будет ли уменьшатся сх после того как мы его достанем из стека и выполним цикл. То есть сначала в сх 8, после того выполнили цикл, он должен стать 7, но поскольку мы достаём из стека сх со значением 8, значит сх не уменьшается. Во общем если сх не уменьшается, то как сделать так что бы программа выполнилась 8 раз и закончилась ?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.04.2016, 16:36
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Вычисления значения функции в формате с плавающей запятой (Assembler):

Вычитание чисел с плавающей запятой в формате double ассемблер - Assembler
Доброго времени суток. Прошу помочь, нужно написать программу:"Вычитание чисел с плавающей точкой в формате double" на языке ассемблер....

Программа для вычисления выражения в формате с плавающей точкой с использованием команд сопроцессора I 80X87 - Assembler
Помогите, пожалуйста, составить программу, а то сессия уже идет :cry: Составить программу на ассемблере для вычисления выражения в...

Запись числа с плавающей запятой в регистр - Assembler
Здравствуйте уважаемые эксперты! Подскажите как записать число с плавающей запятой в регист ax например..

Операции над числами с плавающей запятой - Assembler
Пишу при помощи masm. Изучение ассемблера только начал. Обычно с такими проблемами долго, но все таки мог разобраться сам, но тут я просто...

Вывести с FPU на монитор число с плавающей запятой - Assembler
Доброго времени суток. Мне нужно вывести с FPU на монитор число с плавающей запятой. Пробую вот так: .386 .387 CSEG segment org...

Протабулировать функцию с шагом 0.1 (как работать с числами с плавающей запятой?) - Assembler
Всем привет. Подскажите как организовать цикл на masm32. Нужно протабулировать ф-цию с шагом 0.1. Не знаю как работать с числами с...

20
Полный 30h
Эксперт быдлокодинга
1530 / 442 / 60
Регистрация: 04.11.2010
Сообщений: 1,219
24.04.2016, 21:51 #2
В стек надо заносить СХ после метки начала цикла, а не до неё, а перед командой loop извлекать из стека. Тогда после выполнения команды loop сминусованый СХ будет сохранятся в начале следующего цикла.

Только ИМХО ручной подсчет числа циклов это неправильно. Из цикла надо выходить по проверке условия выхода за диапазон. В данном случае когда Х больше или равен двум.
1
fdrv
1 / 1 / 0
Регистрация: 11.02.2016
Сообщений: 20
24.04.2016, 23:15  [ТС] #3
То есть будет так ?
Assembler
1
2
3
4
5
6
7
8
9
10
    mov ax,DSEG
    mov ds,ax
    mov cx,8  
Start:  push    cx
    call    MULFXX 
    call    MULFYY  
    call    ADDSUBFYZ
    pop cx  
    call    ADDSUBFXDX  
    loop    Start
А какая разница, ведь pop cx и так перед loop находится ?
Или я чего-то не понимаю ?

Добавлено через 2 минуты
Или вы имели ввиду, если разместить команду pop cx непосредственно перед командой loop, то тогда сх сминусуется ?
То есть будет так ?
Assembler
1
2
  pop    cx
    loop    Start
0
Полный 30h
Эксперт быдлокодинга
1530 / 442 / 60
Регистрация: 04.11.2010
Сообщений: 1,219
24.04.2016, 23:23 #4
Цитата Сообщение от fdrv Посмотреть сообщение
А какая разница, ведь pop cx и так перед loop находится ?
Или я чего-то не понимаю ?
Между pop и loop в исходном варианте расположена call ADDSUBFXDX, а по условию
Цитата Сообщение от fdrv Посмотреть сообщение
; заносим в стек сх, по скольку в подпрограммах используется регистр сх
т.е. pop должен идти непосредственно перед самой loop, что бы подпрограмма его не изменила.

Цитата Сообщение от fdrv Посмотреть сообщение
Или вы имели ввиду, если разместить команду pop cx непосредственно перед командой loop, то тогда сх сминусуется ?
То есть будет так ?
Assembler
1
2
pop cx
loop Start
Совершенно верно. Тогда вы получите нетронутый с начала цикла СХ, loop его сминусует, а push в начале следующего цикла уже сминусованый уберёт в стек.
1
fdrv
1 / 1 / 0
Регистрация: 11.02.2016
Сообщений: 20
25.04.2016, 00:11  [ТС] #5
Дошло, спасибо большое !

Добавлено через 4 минуты
А другой вопрос не подскажите ?
Как после выполнения всех подпрограмм занести результат со смещением 4 байта и в какой регистр его лучше занести, то есть после выполнения всех 4-х call-ов нужно занести значение которое получилось, как и куда его лучше будет?
Сначала просто заносим в какой-то регистр, а уже после(остальные 7 раз) мы заносим со смещением 4 байта. Как это реализовать, подскажите пожалуйста ?
0
Полный 30h
Эксперт быдлокодинга
1530 / 442 / 60
Регистрация: 04.11.2010
Сообщений: 1,219
25.04.2016, 01:44 #6
Цитата Сообщение от fdrv Посмотреть сообщение
Как после выполнения всех подпрограмм занести результат со смещением 4 байта и в какой регистр его лучше занести, то есть после выполнения всех 4-х call-ов нужно занести значение которое получилось, как и куда его лучше будет?
Для начала неплохо было бы знать что происходит в ваших подпрограммах. Поясню. Допустим в конце каждого вашего цикла в результате последнего вычисления результат уже находится в каком либо регистре. Тогда целесообразней было бы из этого регистра помещать ответ в ваш массив. (какая то цепочка однотипных вычислений идущих подряд фиксированной длинны обычно называют массивом). В вашем случае это
Assembler
1
massiff DD 8 DUP (0) ; массив из восьми элементов размером dword
Однако поскольку вы работаете с 16 битными регистрами, то поместить результат за "один раз" у вас не получится, так как размер данных в два раза больше чем размер регистра. Поэтому придётся передавать по частям (DW). Для этого, а так же что бы не париться со смещением вам лучше использовать команду stosw она автоматически будет индексировать адрес. Но для этого перед началом цикла Start: необходимо сделать некоторые приготовления.
Assembler
1
lea     di,massiff ; адрес начала массива под ответы поместить в регистр di
тогда в конце каждого цикла вы сможете свой ответ загружать в данный массив командой stosw за два раза.
Условно примем что ваш результат после вычислений находится в регистрах DX - старшая часть, а AX - младшая часть.
Тогда код после последней call будет иметь следующий вид
Assembler
1
2
3
4
lodsw ; младшая часть ответа уходит в massiff по адресу в регистре di? после чего регистр di автоматом увеличивается на два байта
mov ax,dx ; помещаем в ax старшую часть ответа т.к. команда lods работает только с регистром EAX,AX,AL
lodsw ; и соответственно отправляем её из AX на адрес указанный в di. После этого di опять автоматически увеличивается на два байта.
; таким образом в конце каждого цикла мы за два раза по два байта пихаем наш ответ.
1
Mikl___
Заблокирован
Автор FAQ
25.04.2016, 05:21 #7
http://www.cyberforum.ru/cgi-bin/latex.cgi?y=x^{2}-x^{4}=x^{2}(1-x)(1+x)
0
fdrv
1 / 1 / 0
Регистрация: 11.02.2016
Сообщений: 20
25.04.2016, 13:55  [ТС] #8
Цитата Сообщение от Полный 30h Посмотреть сообщение
Допустим в конце каждого вашего цикла в результате последнего вычисления результат уже находится в каком либо регистре.
В последней подпрограмме "call ADDSUBFYZ" я заношу результат в R. Это и есть помещение в массив ?
Вот последние строчки подпрограммы после которой я заношу результат в R
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
; Форматировать результат
@subf9: add ah,ah   ; Знак во флаге переноса
rcr bh,1    ; Знак числа на месте
rcr ah,1    ; Младший бит порядка в АН7
or  ah,7fh  ; Образовать мантиссу
and bl,ah   ; Образовать второй байт числа
@subfa: ret
;
; Сохранить результат
lea di,R
mov [di],si
mov [di+2],bx
Цитата Сообщение от Полный 30h Посмотреть сообщение
massiff DD 8 DUP (0)
у меня это записано вот так
Assembler
1
R   DQ  8 DUP
Цитата Сообщение от Полный 30h Посмотреть сообщение
Однако поскольку вы работаете с 16 битными регистрами, то поместить результат за "один раз" у вас не получится, так как размер данных в два раза больше чем размер регистра.
Простите пожалуйста за скорее всего глупый вопрос. То есть ах, bx, dx, cx - это 16 битные регистры, верно ?

Цитата Сообщение от Полный 30h Посмотреть сообщение
а так же что бы не париться со смещением вам лучше использовать команду stosw она автоматически будет индексировать адрес.
То есть имеется ввиду, оно само будет смещать результат и заносить его в массив при условии, если перед циклом я пропишу строчку
Assembler
1
lea     di,massiff ; адрес начала массива под ответы поместить в регистр di
Но у меня в подпрограммах используется di, можно ли его заменить его или, например как с сх, поместить его в стек, а потом извлечь его и использовать для массива ?

Цитата Сообщение от Полный 30h Посмотреть сообщение
команда lods работает только с регистром EAX,AX,AL
Во время ознакомления с регистрами, где-то вычитал, что когда мы пишем, например регистр ах, то мы сразу указываем и на al(младшая часть) и на ah(старшая часть), или я что-то не так понял ??

Assembler
1
2
3
4
lodsw ; младшая часть ответа уходит в massiff по адресу в регистре di? после чего регистр di автоматом увеличивается на два байта
mov ax,dx ; помещаем в ax старшую часть ответа т.к. команда lods работает только с регистром EAX,AX,AL
lodsw ; и соответственно отправляем её из AX на адрес указанный в di. После этого di опять автоматически увеличивается на два байта.
; таким образом в конце каждого цикла мы за два раза по два байта пихаем наш ответ.
то есть после этих строчок, результат будет заносится в massif(или в моём случае R) и di будет автоматически увеличиваться в итоге на 4 байта(как мне и нужно) и уже при повторении следующий результат будет заносится в 4 байта, на которые di уже увеличился и снова увеличится на 4 байта, после того как я второй раз занесу результат. Верно ?
И это всё реализуется если прописать stosw... а где именно её разместить ?

Фууух.... тяжело
0
Mikl___
Заблокирован
Автор FAQ
25.04.2016, 14:04 #9
fdrv,
по ассемблеру есть много книг, хороших и разных, но прочитай хотя бы вот эту http://www.cyberforum.ru/assembler-articles/thread1005284.html, много времени не займет, а глупые вопросы хоть наполовину отпадут
1
Полный 30h
Эксперт быдлокодинга
1530 / 442 / 60
Регистрация: 04.11.2010
Сообщений: 1,219
25.04.2016, 17:21 #10
Цитата Сообщение от fdrv Посмотреть сообщение
у меня это записано вот так
Assembler
1
R * DQ *8 DUP
Самый натуральный массив. Собственно у меня было предположение для чего он предназначен. Однако меня смутила его размерность. Ведь речь шла о сохранении четырехбайтных результатов DD, а размер ячеек вашего массива восемь байт DQ

Цитата Сообщение от fdrv Посмотреть сообщение
Assembler
1
2
3
4
; Сохранить результат
lea di,R
mov [di],si
mov [di+2],bx
Дело в том, что если такая конструкция у вас будет выполнятся в конце каждого цикла, то независимо от того сколько циклов будет, результат всегда будет попадать в первые четыре байта массива R т.к. команда lea di,R будет каждый раз помещать в регистр di адрес начала массива. Именно поэтому я и порекомендовал вам lea di,massiff, а в вашем случае lea di,R выполнить один раз до начала цикла
а в самом цикле тогда вместо
Assembler
1
2
mov [di],si
mov [di+2],bx
использовать lodsw
Assembler
1
2
3
4
mov ax,si ; младшая часть ответа в ах
lodsw ; младшая часть ответа из ах по адресу в di, а di+2
mov ax,bx ; старшая часть ответа в ах
lodsw ; старшая часть ответа из ах по адресу в di, а di+2
Цитата Сообщение от fdrv Посмотреть сообщение
То есть имеется ввиду, оно само будет смещать результат и заносить его в массив
Да. См. пример кода чуть выше с комментариями

Цитата Сообщение от fdrv Посмотреть сообщение
Но у меня в подпрограммах используется di, можно ли его заменить его или, например как с сх, поместить его в стек, а потом извлечь его и использовать для массива ?
В случае использования команды lodsw, заменить di другим регистром нельзя. Эта команда жестко привязана к регистрам di (адрес) и регистру ах (данные)
А вот стек использовать вполне можно. Равно как и вместо di использовать другой регистр в подпрограммах. Тут уже вы как программист сами решаете что вам эффективней, привычней и т.п.

Цитата Сообщение от fdrv Посмотреть сообщение
Во время ознакомления с регистрами, где-то вычитал, что когда мы пишем, например регистр ах, то мы сразу указываем и на al(младшая часть) и на ah(старшая часть), или я что-то не так понял ??
Совершенно верно. AH и AL это две части части (по 8 бит) одного 16 битного регистра - AX. Тоже самое с BX BH:BL и т.д.
Цитата Сообщение от fdrv Посмотреть сообщение
То есть ах, bx, dx, cx - это 16 битные регистры, верно ?
Верно. Выше как бы попытался донести.

Цитата Сообщение от fdrv Посмотреть сообщение
то есть после этих строчок, результат будет заносится в massif(или в моём случае R) и di будет автоматически увеличиваться в итоге на 4 байта(как мне и нужно) и уже при повторении следующий результат будет заносится в 4 байта, на которые di уже увеличился и снова увеличится на 4 байта, после того как я второй раз занесу результат. Верно ?
И это всё реализуется если прописать stosw... а где именно её разместить ?
Выше я привёл пример какой кусок кода вашей программы нужно заменить.
1
fdrv
1 / 1 / 0
Регистрация: 11.02.2016
Сообщений: 20
25.04.2016, 19:57  [ТС] #11
Задание - Написать программу для решения функцииy=х^2-x^4, где х меняется от -2 до +2 с шагом 0,5. Нужно вычислить функцию на каждом шаге. В формате вычисления с плавающей комой.
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mov ax,DSEG
    mov ds,ax
    mov cx,8
    lea     di,R
    push     di  ; прячем в стек что бы потом вытащить и занести результат всей формулы
Start:  push    cx  ; заносим в стек сх
        call    MULFXX  ; Х возносим в квадрат, результат в Y
    call    MULFYY  ; Х возносим в 4 степень, результат в Z
    pop di ; вытаскиваем di 
        call    ADDSUBFYZ ; подпрограмма в конце которой мы получаем результат выполнения всей формулы и заносим результат в массив(R)
        push    di  ; прячем, поскольку di используется в других регистрах 
    call    ADDSUBFXDX ; выполняем шаг 
        pop cx  ; вытаскиваем 8 для цикла
    loop    Start  ; цикл
; сх и di используются в других регистрах но благодаря стеку, мы их прячем и достаём в нужные моменты
Как-то так. Есть какие нибудь замечания ?

Добавлено через 4 минуты
Цитата Сообщение от Mikl___ Посмотреть сообщение
fdrv,
по ассемблеру есть много книг, хороших и разных, но прочитай хотя бы вот эту http://www.cyberforum.ru/assembler-articles/thread1005284.html, много времени не займет, а глупые вопросы хоть наполовину отпадут
Спасибо Вам за книжку
0
Полный 30h
Эксперт быдлокодинга
1530 / 442 / 60
Регистрация: 04.11.2010
Сообщений: 1,219
25.04.2016, 20:35 #12
Цитата Сообщение от fdrv Посмотреть сообщение
Есть какие нибудь замечания ?
Есть. С работой di в стеке. Она асимметрична. К тому же на первом же проходе значение загруженное в стек из cx вы выталкиваете в di
Assembler
1
2
3
4
Start:  push    cx  ; заносим в стек сх
        call    MULFXX  ; Х возносим в квадрат, результат в Y
    call    MULFYY  ; Х возносим в 4 степень, результат в Z
    pop di ; вытаскиваем di
программа не рабочая.
0
fdrv
1 / 1 / 0
Регистрация: 11.02.2016
Сообщений: 20
25.04.2016, 21:50  [ТС] #13
А если так ?
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    mov ax,DSEG
    mov ds,ax
    mov cx,8
    lea     di,R
    push     di 
Start:  push    cx 
    call    MULFXX 
    call    MULFYY 
    pop cx
    pop di 
    call    ADDSUBFYZ ; в это подпрограмме регистр сх не используется
    push    di 
    call    ADDSUBFXDX ; в это подпрограмме регистр сх тоже не используется
    loop    Start
И ещё вопрос по поводу di, до цикла прописано lea di,R и после занесли в стек, но потом выносим из стека перед call ADDSUBFYZ(тут же, в конце,используется команда lodsw которую Вы мне посоветовали), но в этой подпрограмме используется регистр di как вначале так и походу самой подпрограммы, это не как не повлияет на то что потом в конце мы заносим туда результат ?
0
Полный 30h
Эксперт быдлокодинга
1530 / 442 / 60
Регистрация: 04.11.2010
Сообщений: 1,219
26.04.2016, 00:00 #14
Цитата Сообщение от fdrv Посмотреть сообщение
А если так ?
В принципе ошибок я не вижу. Единственное "НО" у вас до цикла стек уменьшается на два байта push di перед Start:, но по выходу из цикла нет обратной команды выравнивающей стек.
Цитата Сообщение от fdrv Посмотреть сообщение
но в этой подпрограмме используется регистр di как вначале так и походу самой подпрограммы, это не как не повлияет на то что потом в конце мы заносим туда результат ?
Я ничего по этому поводу сказать не могу. Код данной подпрограммы видимо засекречен.
1
fdrv
1 / 1 / 0
Регистрация: 11.02.2016
Сообщений: 20
26.04.2016, 03:46  [ТС] #15
Цитата Сообщение от Полный 30h Посмотреть сообщение
но по выходу из цикла нет обратной команды выравнивающей стек
Выравнивать стек ? А можно по подробнее, то есть мы занесли di и стек соответственно стал меньше, ну это хоть я понял, что если мы ложим что-то в корзиночку, то она становится менее вместительна. А по выходу из цикла, то есть после того как 8 кругов намотает, мы должны стек выравнять, что это значит ?
Или это к тому что у меня просто после loop Start не единой команды ? Если да, то такой вопрос, если допустим что у меня всё правильно и в массиве находятся все 8 результатов, то после loop Start можно просто END написать ? или я опять что-то элементарное не знаю ?
Простите за многословность

Код подпрограммы (не мой, хотя думаю Вы это и так поняли)
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
Start:          lea si,Y
lea di,Z
mov bx,[si+2]
mov si,[si]
mov dx,[di+2]
mov di,[di]
; Переход к подпрограммам сложения, вычитания
call    ADDSUBF
ADDSUBF PROC
 
; Сравнить знаки операндов и определить операцию
@addf:  mov al,bh   ; Сравнить
xor     al,dh   ; знаки операндов
jns     @addf1  ; Знаки операндов одинаковы
xor     dh,80h  ; Знаки различны,
jmp     @subf   ; перейти к вычитанию
;
; Проверить операнды на нуль
@addf1: mov ax,dx   ; Проверить на нуль
or  ax,di   ;   второй операнд
jz  @addf8  ;   Результат в BX:SI
mov ax,bx   ;   Проверить на нуль
or  ax,si   ;   первый операнд
jnz @addf2  ;   Оба операнда не нулевые
xchg    bx,dx   ;   Первый операнд равен нулю,
xchg    si,di   ;   сумма равна
jmp @addf8  ;   второму операнду
;
; Оба операнда не нулевые можно складывать.
@addf2: mov ah,bh   ; Сравнить общий знак в АН
shl bx,1    ; Восстановить скрытый бит
stc ; мантиссы первого операнда
rcr bl,1
shl dx,1    ; Восстановить скрытый бит
stc ; мантиссы второго операнда
rcr dl,1
; Сранить порядки, образовать разность порядков
cmp bh,dh   ; Сравнить порядки
jnc @addf3  ; Порядок числа в BX:SI больше
xchg    bx,dx   ; Передать большее число
xchg    si,di   ; в BX:SI
@addf3: sub bh,dh   ; Образовать разность порядков
jz  @addf6  ; Порядки одинаковы
cmp bh,24   ; Сравнить разность порядков с 24
jc  @addf5  ; Разность порядков меньше 24
jmp @addf7  ; Результата в BX:SI
; Необходимо сдвигать вправо мантиссу меньшего числа в DL:DI 
@addf5: shr     dl,1    ; Сдвинуть мантиссу
rcr di,1
inc dh      ; Увеличить меньший порядок
dec bh      ; Декремент разности порядков
jnz @addf5  ; Повторять сдвиг
mov bh,dh   ; Передать порядок в BH
;
; Можно складывать мантиссы. В регистре DH общий порядок 
@addf6: add     si,di   ; Сложить младшие части мантисс
adc     bl,dl   ; Сложить старшие части мантисс
jnc     @addf7  ; Нарушения нормализации влево нет
inc     dh      ; Скорректировать порядок
cmp     dh,255  ; Проверить переполнение
stc
jz  @addf8  ; Возникло пререполнение
rcr bl,1    ; Сдвинуть
rcr si,1    ; мантиссу вправо
mov bh,dh   ; Передать порядок в BH
;
; Форматировать результат
@addf7: add ah,ah   ; Знак во флаге переноса
rcr bh,1    ; Знак числа на месте
rcr ah,1    ; Младший бит порядка в АН7
or  ah,7fh  ; Образовать мантиссу
and bl,ah   ; Образовать второй байт числа
@addf8: ret
;
; Сохранить результат
lea di,Z
mov [di],si
mov [di+2],bx
jmp Start   ;ret
 
@subf:
; Проверить операнды на нуль
@subf1: mov ax,dx   ; Проверить на нуль
or  ax,di   ;   второй операнд
jz  @subfa  ;   Результат в BX:SI
mov ax,bx   ;   Проверить на нуль
or  ax,si   ;   первый операнд
jnz @subf2  ;   Оба операнда не нулевые
xchg    bx,dx   ;   Первый операнд равен нулю,
xchg    si,di   ;   разность равна
xor bh,80h  ;   второму операнду
jmp @subfa  ;   с измененным знаком
;
; Оба операнда не нулевые можно вычитать.
@subf2: mov ah,bh   ; Сохранить знак уменьшаемого
shl bx,1    ; Восстановить скрытый бит
stc ; мантиссы уменьшаемого
rcr bl,1
shl dx,1    ; Восстановить скрытый бит
stc ; мантиссы вычитаемого
rcr dl,1
; Проверить отношения между числами
cmp bh,dh   ;   Сравнить порядки
jnz @subf3  ;   Порядки не равны
cmp bl,dl   ;   Сранить старшие байты мантисс
jnz @subf3  ;   Они не равны
cmp si,di   ;   Сравнить младшие слова мантисс
jnz @subf3  ;   Они не равны
mov bx,0    ;   Числа равны,
mov si,0    ;   разность равна нулю
jmp @subfa
; Операнды не равны, необходимо вычитать.
@subf3: jnc @subf4  ; Уменьшаемое больше вычитаемого
xchg    bx,dx   ; Вычитаемое больше уменьшаемого,
xchg    si,di   ; обменять числа
xor ah,80h  ; Изменить знак результата
; Образовать разность порядков.
@subf4: sub bh,dh   ; Разность порядков в BH
jz  @subf7  ; Порядки одинаковы
cmp bh,24   ; Сравнить разность порядков с 24
jc  @subf6  ; Разность порядков меньше 24
jmp @subf9  ; Результата в BX:SI
; Необходимо сдвигать вправо мантиссу менишего числа в DL:DI 
@subf6: shr     dl,1    ; Сдвинуть мантиссу
rcr di,1
inc dh      ; Увеличить меньший порядок
dec bh      ; Декремент разности порядков
jnz @subf6  ; Повторять сдвиг
mov bh,dh   ; Передать общий порядок в BH
; Вычитание мантисс и образование результата.
@subf7: sub si,di   ; Вычесть мантиссы
sbb bl,dl
@subf8: or  bl,bl   ; Проверить старший бит мантиссы
js      @subf9  ;   Результат нормализован
dec     bh  ;   Декремент порядка
cmp     bh,255  ;   Проверить переполнение
stc ;   Установить флаг переноса
jz      @subfa  ;   Возникло антипереполнение
shl     si,1    ;   Сдвинуть мантиссу влево
rcl bl,1
jmp @subf8  ; Повторять до нормализации
; Форматировать результат
@subf9: add ah,ah   ; Знак во флаге переноса
rcr bh,1    ; Знак числа на месте
rcr ah,1    ; Младший бит порядка в АН7
or  ah,7fh  ; Образовать мантиссу
and bl,ah   ; Образовать второй байт числа
@subfa: ret
;
; Сохранить результат
mov ax,si   ; младшая часть ответа в ах
lodsw       ; младшая часть ответа из ах по адресу di, а di+2
mov ax,bx   ; старшая часть ответа в ах
lodsw       ; старшая часть ответа из ах по адресу di, а di+2
 
ADDSUBF ENDP
0
26.04.2016, 03:46
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.04.2016, 03:46
Привет! Вот еще темы с ответами:

Составить программу для вычисления значения функции y = f(x) - Assembler
Доброго времени суток. такой вопрос: Составить программу для вычисления значения функции y = f(x). Реализовать полным ветвлением. ...

Написать программу вычисления значения функции при любом X - Assembler
Написать программу вычисления значения функции при любом X. Написать на языке Assembler

Ввод с клавиатуры значения=>работа функции=>вывод значения на экран - Assembler
Есть функция факториала: SECTION .start global _start _start: mov eax, 10; mov ecx, eax; mov ebx, 1; for_loop: imul ebx,...

Вычислить заданное целочисленное выражение для данных в формате INTEGER переменные a, b, а X в формате LONGINT - Assembler
1. Написать на языке ассемблера процедуру, вычисляющее заданное значение по входным переменным; 2. Написать программу на C++/Assembler,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.