С Новым годом! Форум программистов, компьютерный форум, киберфорум
Assembler: математика, вычисления
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
36 / 1 / 1
Регистрация: 08.02.2018
Сообщений: 7
TASM

Вычислить гиперболический синус

10.03.2019, 03:16. Показов 3788. Ответов 6

Студворк — интернет-сервис помощи студентам
Здравствуйте. В универе задали лабу по ассемблерам TASM. Задание с помощью сопроцессора вычислить гиперболический синус (e^x-e^-x)/2.
Я разобрался с вводом и выводом вещественного числа с клавиатуру, застрял на вычисление самого синуса.
Вот отрывок кода
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
;получаю е^x
   fldl2e;  TOPSWR-=1; ST(0)=1.4426950408;  Загрузка log2e
   fmul st(0),st(1);dst = dst * src;    Умножение вещественное
   fld     st(0);TOPSWR-=1; ST(0)=src;  Загрузка операнда в вершину стека
   frndint                  ;ST(0)=(ST(0))  Округление ST(0)
   fsub    st(1); st;dst = dst — src; Вычитание вещественное
   fxch    st(1);ST(0) ↔ ST(i)    Обмен значений ST(0) и ST(i)
   f2xm1;ST(0)=2ST(0)-1;    Вычисление выражения y=2x-1
   fld1;TOPSWR-=1; ST(0)=1; Загрузка 1
   fadd;dst = dst + src;    Сложение вещественное
   fscale;ST(0) = ST(0) · 2ST(1)   Масштабирование по степеням 2
   fstp    st(1);dst=ST(0); TOPSWR+=1;  Сохранение вершины стека в память с выталкиванием
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;теперь считаю е^-x
   fld st(1); Загрузка операнда в вершину стека, в st(1), как я понимаю находиться x;ВИДИМО ЗДЕСЬ ОШИБКА
   fchs; меняю знак
   fldl2e
   fmul
   fld     st(0)
   frndint
   fsub    st(1), st(0)
   fxch    st(1)
   f2xm1
   fld1
   fadd
   fscale
   fstp    st(1)
Просто e^x он выводить правильно, но e^-x неправильно, думаю проблема в стеке, потому что когда я отдельно компилирую участок кода с -х или х то все работает хорошо, но когда я комбинирую их, то значение левый выходят.
Я вычислю e^x и он у меня выталкивается и значение х переходит в стек st(1), поэтому я его загружаю в вершину стека и повторяю код только с отрицательным х, но в реальности это не работает. Видимо неправильно ориентируюсь в стеке
Не судите строго-новичок в ассемблере.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.03.2019, 03:16
Ответы с готовыми решениями:

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

Гиперболический синус
ребят помогите! не знаю как в дельфи задать гиперболический синус. sh(x) - гиперболический синус. не знаю как записать чтоб работал....

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

6
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8647 / 4482 / 1669
Регистрация: 01.02.2015
Сообщений: 13,889
Записей в блоге: 12
10.03.2019, 04:15
Самое лучшее - выполнять по шагам в отладчике и наблюдать за изменением стека FPU.

У вас должно быть подобие
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        ;вычисление с использованием трансцендентных команд сопроцессора
        finit
        fld     [X]
        fld     st(0)
        call    Exp
        fxch    st(1)
        fchs
        call    Exp
        fsubp   st(1),  st(0)
        fld1
        fadd    st(0),  st(0)
        fdivp   st(1),  st(0)
        ;сохранение результата
        fstp    [Result]
А по обрывку не видно, как загружается X в стек, сколько раз.

Добавлено через 5 минут
Или совсем один раз вычислять exp(x) и разместив его в стеке три раза применить для сложения и деления:
https://www.cyberforum.ru/cgi-bin/latex.cgi?T={e}^{x}

https://www.cyberforum.ru/cgi-bin/latex.cgi?sh(x)=\frac{T-\frac{1}{T}}{2}=\frac{T^2-1}{2T}

https://www.cyberforum.ru/cgi-bin/latex.cgi?sh(x)=\frac{T^2-1}{2T}
1
36 / 1 / 1
Регистрация: 08.02.2018
Сообщений: 7
10.03.2019, 15:10  [ТС]
Спасибо за ответ. Я решил использовать второй способ, досчитал до T2-1, а дальше не идет. Вот вся программа:
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
model small
.code
.386
start:
mov ax, @data
mov ds, ax
 
finit;инициализация FPU, устанавливает некоторые регистры FPU в их начальное состояние, незавимо от предыдущих значений
call read_float
push 10
call OutFloat
 
 
xor ax, ax
int 16h
.exit
two equ word ptr [bp-1]
ten equ word ptr [bp-2]
temp equ word ptr [bp-4]
 
 
read_float proc
enter 4, 0;создаёт стековый кадр заданного размера и уровня вложенности с целью вызова процедуры
mov ten, 10
fldz;Загрузка 0 в стек
mov ah, 01h
int 21h
xor bx, bx ; sign обнуляем XOR (НЕ ИЛИ)устанавливает бит результата в 1, если бит источника отличается от бита приемника.
cmp al, '-';Выполнить команду CPM Прочитать флаг ZF Если ZF = 1, то числа равны Если ZF = 0, то числа НЕ равны
jne @read_float2;jne будет осуществляться тогда, когда значение флага ZF равно 0
xor bx, 1
@read_float1:
mov ah, 01h
int 21h
@read_float2:
cmp al, '.'
je  @read_float3;Инструкция JE выполняет короткий переход, если первый операнд РАВЕН второму операнду при выполнении операции сравнения с помощью команды CMP
cmp al, '9'
ja  @read_float6;JA/JNBE - переход, если больше/переход, если не меньше и не равно.
sub al, '0'
jb  @read_float6;если меньше 
cbw;выполняет преобразование байта в слово
mov temp, ax
fimul ten
fiadd temp
jmp  @read_float1
@read_float3:
fld1
@read_float4:
mov ah, 01h
int 21h
cmp al, '9'
ja  @read_float5
sub al, '0'
jb  @read_float5
cbw
mov temp, ax
fidiv ten;ST(0) = ST(0) / src;  Деление целочисленное
fld  st(0);Загрузка операнда в вершину стека
fimul temp; ST(0) = ST(0) * src;    Умножение целочисленное
faddp st(2), st;Сложение вещественное с выталкиванием ST(i) = ST(i) + ST(0); 
jmp  short @read_float4
@read_float5:
fstp st(0);Сохранение вершины стека в память с выталкиванием
@read_float6:
mov  al, 10
int  29h
or bx, bx
jz @q;перейти если ноль
fchs;   Изменение знака ST(0) = -ST(0)    Изменение знака
@q:
;///////////////////////////////////////////////////////////////////
 
   fldl2e
   fmul
   fld     st(0)
   frndint
   fsub    st(1), st(0)
   fxch    st(1)
   f2xm1
   fld1
   fadd
   fscale 
   f2xm1
   FLD st(0)
   fmul
   fld1
   fsub st(1), st(0)
   fxch    st(1)
   fstp    st(1); здесь в OutFloat proc выводить T^2-1 правильно
 
;///////////////////////////////////////////////////////////////
 
leave
ret
read_float endp
 
length_frac     equ     [bp+4]
 
OutFloat proc   near
        enter   4, 0            ; пролог - выделим в кадре стека 4 байта под локальные переменные
        mov     ten, 10
        ftst                    ; определяем знак числа Анализ ST(0) (сравнение с нулем)
        fstsw   ax;Считать слово состояния сопроцессора в память
        sahf;сохранить Ah в ригстре флагов 
        jnc     @positiv;перейти если нет знака
        mov     al, '-'         ; если число отрицательное - выводим минус
        int     29h
        fchs                    ; и получаем модуль числа
@positiv:
        fld1                    ; загружаем единицу
        fld     st(1)           ; копируем число на вершину стека
        fprem                   ; выделим дробную часть,Частичный остаток от деления ST(0)=ST(0)-Q*ST(1)
        fsub    st(2), st       ; отнимем ее от числа - получим целую часть Вычитание вещественное
        fxch    st(2)           ; меняем местами целую и дробную части
        xor     cx, cx          ; обнуляем счетчик
; далее идет стандартный алгоритм вывода целого числа на экран
@1:
        fidiv   ten             ; делим целую часть на десять
        fxch    st(1)           ; обменяем местами st и st(1) для команды fprem
        fld     st(1)           ; копируем результат на вершину стека
        fprem                   ; выделим дробную часть (цифру справа от целой части)
        fsub    st(2), st       ; получим целую часть
        fimul   ten             ; *10
        fistp   temp            ; получаем очередную цифру
        push    temp            ; заталкиваем ее глубже в стек
        inc     cx              ; и увеличим счетчик
        fxch    st(1)           ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1)
        ftst                    ; проверим не получили ли в частном 0?
        fstsw   ax
        sahf
        jnz     @1              ; нет - продолжим цикл
@2:                             ; извлекаем очередную цифру, переводим её в символ и выводим.
        pop     ax
        add     al, '0'
        int     29h
        loop    @2
; далее то же самое, только для дробной части. Алгоритм похож на вывод целого числа, только вместо деления умножение и проход по числу слева
        fstp    st              ; сначала проверим, есть ли дробная часть
        fxch    st(1)
        ftst
        fstsw   ax
        sahf
        jz      @quit           ; дробная часть отсутствует
        mov     al, '.'
        int     29h             ; если присутствует - выведем точку
        mov     cx, length_frac ; помещаем в счетчик длину дробной части
@3:
        fimul   ten             ; умножим на 10
        fxch    st(1)           ; подготовка для fprem - меняем st и st(1) местами и
        fld     st(1)           ; копируем число на вершину
        fprem                   ; отделим дробную часть от целой
        fsub    st(2), st       ; и оставляем дробную
        fxch    st(2)
        fistp   temp            ; выталкиваем полученное число из стека в temp
        mov     ax, temp        ; по дробной части идем слева, значит число выводим сразу, без предварительного сохранения в стек
        or      al, 30h         ; перевод в ascii
        int     29h             ; на экран
        fxch    st(1)           ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1)
        ftst
        fstsw   ax
        sahf                    ; проверим на 0 остаток дробной части
        loopne  @3
@quit:
        fstp                    ; готово. Чистим стек сопроцессора
        fstp    st
        leave                   ; эпилог
        ret     2
OutFloat endp
 
 
end start
Я пытаюсь пошагово считать и выводить ответ, дабы не ошибиться. У меня возникают трудности в понимании стека
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   fldl2e
   fmul
   fld     st(0)
   frndint
   fsub    st(1), st(0)
   fxch    st(1)
   f2xm1
   fld1
   fadd
   fscale 
   f2xm1
   FLD st(0)
   fmul
   fld1
   fsub st(1), st(0);получается у меня в st(0) находится 1, в st(1) = T^2-1, а в st(2)=T
;поэтому я меняю местами st(0) и st(1) и выталкиваю st(0) и в OutFloat proc выводиться T^2-1  
   
   fxch    st(1)
   fstp    st(1)
Дальше я пытаюсь проделать это
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   fldl2e
   fmul
   fld     st(0)
   frndint
   fsub    st(1), st(0)
   fxch    st(1)
   f2xm1
   fld1
   fadd
   fscale 
   f2xm1
   FLD st(0)
   fmul
   fld1
   fsub st(1), st(0)
   fld     st(2);в st(0) как я понимаю находиться T
   fadd st(0),st(3)
   fdiv st(2), st(0)
   fxch    st(2)
   fstp    st(1); тут он должен выводить (T^2-1)/2T, но не выводит!
Еще вопрос, как отслеживать стек FPU в отладчике Turbo Debugger?
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8647 / 4482 / 1669
Регистрация: 01.02.2015
Сообщений: 13,889
Записей в блоге: 12
10.03.2019, 15:27
Не все TD показывают стек FPU - нужно пробовать из TASM 2.0 или TASM 3.0 или TASM 4.0.
Показывает только один из них, а остальные - что всё равно нулям.

F10 - View - Numeric Processor

А дальше или мышкой или Shift-F5 и Ctrl-F5 перемещать и менять размер стрелками.

Добавлено через 1 минуту
Я не пойму ваш код. Там ввод, потом вывод числа. А где рассчёты?

Добавлено через 1 минуту
Вы показываете какие-то расчёты. Я даже проверить их не могу. Откуда они?
1
36 / 1 / 1
Регистрация: 08.02.2018
Сообщений: 7
10.03.2019, 15:31  [ТС]
74 строчка расчеты
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
model small
.code
.386
start:
mov ax, @data
mov ds, ax
 
finit;инициализация FPU, устанавливает некоторые регистры FPU в их начальное состояние, незавимо от предыдущих значений
call read_float
push 10
call OutFloat
 
 
xor ax, ax
int 16h
.exit
two equ word ptr [bp-1]
ten equ word ptr [bp-2]
temp equ word ptr [bp-4]
 
 
read_float proc
enter 4, 0;создаёт стековый кадр заданного размера и уровня вложенности с целью вызова процедуры
mov ten, 10
fldz;Загрузка 0 в стек
mov ah, 01h
int 21h
xor bx, bx ; sign обнуляем XOR (НЕ ИЛИ)устанавливает бит результата в 1, если бит источника отличается от бита приемника.
cmp al, '-';Выполнить команду CPM Прочитать флаг ZF Если ZF = 1, то числа равны Если ZF = 0, то числа НЕ равны
jne @read_float2;jne будет осуществляться тогда, когда значение флага ZF равно 0
xor bx, 1
@read_float1:
mov ah, 01h
int 21h
@read_float2:
cmp al, '.'
je  @read_float3;Инструкция JE выполняет короткий переход, если первый операнд РАВЕН второму операнду при выполнении операции сравнения с помощью команды CMP
cmp al, '9'
ja  @read_float6;JA/JNBE - переход, если больше/переход, если не меньше и не равно.
sub al, '0'
jb  @read_float6;если меньше 
cbw;выполняет преобразование байта в слово
mov temp, ax
fimul ten
fiadd temp
jmp  @read_float1
@read_float3:
fld1
@read_float4:
mov ah, 01h
int 21h
cmp al, '9'
ja  @read_float5
sub al, '0'
jb  @read_float5
cbw
mov temp, ax
fidiv ten;ST(0) = ST(0) / src;  Деление целочисленное
fld  st(0);Загрузка операнда в вершину стека
fimul temp; ST(0) = ST(0) * src;    Умножение целочисленное
faddp st(2), st;Сложение вещественное с выталкиванием ST(i) = ST(i) + ST(0); 
jmp  short @read_float4
@read_float5:
fstp st(0);Сохранение вершины стека в память с выталкиванием
@read_float6:
mov  al, 10
int  29h
or bx, bx
jz @q;перейти если ноль
fchs;   Изменение знака ST(0) = -ST(0)  Изменение знака
@q:
;///////////////////////////////////////////////////////////////////
 
   fldl2e
   fmul
   fld     st(0)
   frndint
   fsub    st(1), st(0)
   fxch    st(1)
   f2xm1
   fld1
   fadd
   fscale 
   f2xm1
   FLD st(0)
   fmul
   fld1
   fsub st(1), st(0)
   fxch    st(1)
   fstp    st(1); здесь в OutFloat proc выводить T^2-1 правильно
 
;///////////////////////////////////////////////////////////////
 
leave
ret
read_float endp
 
length_frac     equ     [bp+4]
 
OutFloat proc   near
        enter   4, 0            ; пролог - выделим в кадре стека 4 байта под локальные переменные
        mov     ten, 10
        ftst                    ; определяем знак числа Анализ ST(0) (сравнение с нулем)
        fstsw   ax;Считать слово состояния сопроцессора в память
        sahf;сохранить Ah в ригстре флагов 
        jnc     @positiv;перейти если нет знака
        mov     al, '-'         ; если число отрицательное - выводим минус
        int     29h
        fchs                    ; и получаем модуль числа
@positiv:
        fld1                    ; загружаем единицу
        fld     st(1)           ; копируем число на вершину стека
        fprem                   ; выделим дробную часть,Частичный остаток от деления ST(0)=ST(0)-Q*ST(1)
        fsub    st(2), st       ; отнимем ее от числа - получим целую часть Вычитание вещественное
        fxch    st(2)           ; меняем местами целую и дробную части
        xor     cx, cx          ; обнуляем счетчик
; далее идет стандартный алгоритм вывода целого числа на экран
@1:
        fidiv   ten             ; делим целую часть на десять
        fxch    st(1)           ; обменяем местами st и st(1) для команды fprem
        fld     st(1)           ; копируем результат на вершину стека
        fprem                   ; выделим дробную часть (цифру справа от целой части)
        fsub    st(2), st       ; получим целую часть
        fimul   ten             ; *10
        fistp   temp            ; получаем очередную цифру
        push    temp            ; заталкиваем ее глубже в стек
        inc     cx              ; и увеличим счетчик
        fxch    st(1)           ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1)
        ftst                    ; проверим не получили ли в частном 0?
        fstsw   ax
        sahf
        jnz     @1              ; нет - продолжим цикл
@2:                             ; извлекаем очередную цифру, переводим её в символ и выводим.
        pop     ax
        add     al, '0'
        int     29h
        loop    @2
; далее то же самое, только для дробной части. Алгоритм похож на вывод целого числа, только вместо деления умножение и проход по числу слева
        fstp    st              ; сначала проверим, есть ли дробная часть
        fxch    st(1)
        ftst
        fstsw   ax
        sahf
        jz      @quit           ; дробная часть отсутствует
        mov     al, '.'
        int     29h             ; если присутствует - выведем точку
        mov     cx, length_frac ; помещаем в счетчик длину дробной части
@3:
        fimul   ten             ; умножим на 10
        fxch    st(1)           ; подготовка для fprem - меняем st и st(1) местами и
        fld     st(1)           ; копируем число на вершину
        fprem                   ; отделим дробную часть от целой
        fsub    st(2), st       ; и оставляем дробную
        fxch    st(2)
        fistp   temp            ; выталкиваем полученное число из стека в temp
        mov     ax, temp        ; по дробной части идем слева, значит число выводим сразу, без предварительного сохранения в стек
        or      al, 30h         ; перевод в ascii
        int     29h             ; на экран
        fxch    st(1)           ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1)
        ftst
        fstsw   ax
        sahf                    ; проверим на 0 остаток дробной части
        loopne  @3
@quit:
        fstp                    ; готово. Чистим стек сопроцессора
        fstp    st
        leave                   ; эпилог
        ret     2
OutFloat endp
 
 
end start
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8647 / 4482 / 1669
Регистрация: 01.02.2015
Сообщений: 13,889
Записей в блоге: 12
10.03.2019, 15:35
Нет. Это неправильно.
В основной программе ввод, расчёты, вывод. Не надо смешивать всё подряд. Процедура называется ВВОД_ЧИСЛА, не надо смешивать. Отсюда и все проблемы - вы не знаете что творится в стеке.
0
36 / 1 / 1
Регистрация: 08.02.2018
Сообщений: 7
10.03.2019, 17:55  [ТС]
Лучший ответ Сообщение было отмечено ФедосеевПавел как решение

Решение

ОК, спасибо. Нашел у себя в отладчике таблицу стека, попробую создать proc для расчета

Добавлено через 2 часа 16 минут
Все получилось. Ошибка в том, что я неправильно понимал механизм изменения стека в некоторых командах, с окошком стека в отладчике легко нашел ошибку
Получилось как-то так
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
model small
.code
.386
start:
mov ax, @data
mov ds, ax
 
finit;инициализация FPU, устанавливает некоторые регистры FPU в их начальное состояние, незавимо от предыдущих значений
call read_float
call Compute
push 10
call OutFloat
 
 
xor ax, ax
int 16h
.exit
ten equ word ptr [bp-2]
temp equ word ptr [bp-4]
 
 
read_float proc
enter 4, 0;создаёт стековый кадр заданного размера и уровня вложенности с целью вызова процедуры
mov ten, 10
fldz;Загрузка 0 в стек
mov ah, 01h
int 21h
xor bx, bx ; sign обнуляем XOR (НЕ ИЛИ)устанавливает бит результата в 1, если бит источника отличается от бита приемника.
cmp al, '-';Выполнить команду CPM Прочитать флаг ZF Если ZF = 1, то числа равны Если ZF = 0, то числа НЕ равны
jne @read_float2;jne будет осуществляться тогда, когда значение флага ZF равно 0
xor bx, 1
@read_float1:
mov ah, 01h
int 21h
@read_float2:
cmp al, '.'
je  @read_float3;Инструкция JE выполняет короткий переход, если первый операнд РАВЕН второму операнду при выполнении операции сравнения с помощью команды CMP
cmp al, '9'
ja  @read_float6;JA/JNBE - переход, если больше/переход, если не меньше и не равно.
sub al, '0'
jb  @read_float6;если меньше 
cbw;выполняет преобразование байта в слово
mov temp, ax
fimul ten
fiadd temp
jmp  @read_float1
@read_float3:
fld1
@read_float4:
mov ah, 01h
int 21h
cmp al, '9'
ja  @read_float5
sub al, '0'
jb  @read_float5
cbw
mov temp, ax
fidiv ten;ST(0) = ST(0) / src;  Деление целочисленное
fld  st(0);Загрузка операнда в вершину стека
fimul temp; ST(0) = ST(0) * src;    Умножение целочисленное
faddp st(2), st;Сложение вещественное с выталкиванием ST(i) = ST(i) + ST(0); 
jmp  short @read_float4
@read_float5:
fstp st(0);Сохранение вершины стека в память с выталкиванием
@read_float6:
mov  al, 10
int  29h
or bx, bx
jz @q;перейти если ноль
fchs;   Изменение знака ST(0) = -ST(0)    Изменение знака
 
@q:
leave
ret
read_float endp
 
Compute proc
 
   enter 4, 0;  
   fld     st(0)
   FABS
   fldl2e
   fmul
   fld     st(0)
   frndint
   fsub    st(1), st(0)
   fxch    st(1)
   f2xm1
   fld1
   fadd
   fscale 
   f2xm1
   fld     st(0)
   FLD st(0)
   fmul
   fld1
   fsub st(1), st(0)
   fld     st(2);в st(0) как я понимаю находиться T
   fadd st(0),st(3)
   fdiv st(2), st(0)
   fxch    st(2)
   fstp    st(1); тут он должен выводить (T^2-1)/2T, но не выводит!
   
   fldz
   fcom st(5) 
   fstsw ax
   sahf
   jb @e
   fxch   st(1)
   FCHS
   fld st(0)
@e:  
   fxch   st(1)
   fstp    st(1)
Compute endp
 
length_frac     equ     [bp+4]
 
OutFloat proc   near
        enter   4, 0            ; пролог - выделим в кадре стека 4 байта под локальные переменные
        mov     ten, 10
        ftst                    ; определяем знак числа Анализ ST(0) (сравнение с нулем)
        fstsw   ax;Считать слово состояния сопроцессора в память
        sahf;сохранить Ah в ригстре флагов 
        jnc     @positiv;перейти если нет знака
        mov     al, '-'         ; если число отрицательное - выводим минус
        int     29h
        fchs                    ; и получаем модуль числа
@positiv:
        fld1                    ; загружаем единицу
        fld     st(1)           ; копируем число на вершину стека
        fprem                   ; выделим дробную часть,Частичный остаток от деления ST(0)=ST(0)-Q*ST(1)
        fsub    st(2), st       ; отнимем ее от числа - получим целую часть Вычитание вещественное
        fxch    st(2)           ; меняем местами целую и дробную части
        xor     cx, cx          ; обнуляем счетчик
; далее идет стандартный алгоритм вывода целого числа на экран
@1:
        fidiv   ten             ; делим целую часть на десять
        fxch    st(1)           ; обменяем местами st и st(1) для команды fprem
        fld     st(1)           ; копируем результат на вершину стека
        fprem                   ; выделим дробную часть (цифру справа от целой части)
        fsub    st(2), st       ; получим целую часть
        fimul   ten             ; *10
        fistp   temp            ; получаем очередную цифру
        push    temp            ; заталкиваем ее глубже в стек
        inc     cx              ; и увеличим счетчик
        fxch    st(1)           ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1)
        ftst                    ; проверим не получили ли в частном 0?
        fstsw   ax
        sahf
        jnz     @1              ; нет - продолжим цикл
@2:                             ; извлекаем очередную цифру, переводим её в символ и выводим.
        pop     ax
        add     al, '0'
        int     29h
        loop    @2
; далее то же самое, только для дробной части. Алгоритм похож на вывод целого числа, только вместо деления умножение и проход по числу слева
        fstp    st              ; сначала проверим, есть ли дробная часть
        fxch    st(1)
        ftst
        fstsw   ax
        sahf
        jz      @quit           ; дробная часть отсутствует
        mov     al, '.'
        int     29h             ; если присутствует - выведем точку
        mov     cx, length_frac ; помещаем в счетчик длину дробной части
@3:
        fimul   ten             ; умножим на 10
        fxch    st(1)           ; подготовка для fprem - меняем st и st(1) местами и
        fld     st(1)           ; копируем число на вершину
        fprem                   ; отделим дробную часть от целой
        fsub    st(2), st       ; и оставляем дробную
        fxch    st(2)
        fistp   temp            ; выталкиваем полученное число из стека в temp
        mov     ax, temp        ; по дробной части идем слева, значит число выводим сразу, без предварительного сохранения в стек
        or      al, 30h         ; перевод в ascii
        int     29h             ; на экран
        fxch    st(1)           ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1)
        ftst
        fstsw   ax
        sahf                    ; проверим на 0 остаток дробной части
        loopne  @3
@quit:
        fstp                    ; готово. Чистим стек сопроцессора
        fstp    st
        leave                   ; эпилог
        ret     2
OutFloat endp
 
 
end start
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
10.03.2019, 17:55
Помогаю со студенческими работами здесь

Как записать Гиперболический синус
Добрый день. Нужно записать эту функцию: f(x)=3*sh{(0.75*x)}^{2}-5*ch(1.25*x) в паскале , я записал ее так:...

Гиперболический синус SH(x), разложение в ряд
Всем здравствуйте мне очень нужно помочь решить задачу на паскале, пожалуйста: известно, что гиперболический синус SH(x) может быть...

Взаимодействие си и ассемблера (гиперболический синус и косинус)
#include <stdio.h> #include <math.h> #define EPS 1e-10 double Sh(double x) { int i; double t, k, p, eps; t=p=x; k=1; ...

Гиперболический Синус в ряд - неправильный подсчет
Имеется ряд sh(x) = Сумма от i до N 1/(2i+1)!*x2i+1 вот код#include <iostream> #include <fstream> #include <math.h> using...

Написать функцию, которая находит гиперболический синус
3)Структуризация программ. Функции: Написать функцию, которая находит гиперболический синус и реализуется формуле:y=sh(x)=(e^x-e^-x)/2.


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Old Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru