Форум программистов, компьютерный форум, киберфорум
Наши страницы
Assembler для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
cinekst_207
0 / 0 / 5
Регистрация: 25.03.2018
Сообщений: 50
1

Вычитание чисел в формате BCD

19.04.2018, 13:12. Просмотров 829. Ответов 10
Метки нет (Все метки)

Введите два десятичных числа разрядностью не более 10 цифр, выполните преобразование в неупакованный BCD-формат, вычтете второе из первого и выведите результат.
В общем я вроде минусы учёл(отриц. числа) но при вводе отриц. и пол.(или пол. и отриц.) выдаёт чушь (например -2 и 2 выдаст 199999999=0). Что не так? Сложение (ADDI) вроде верное?
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
.model  SMALL
        STACK  100h
        DATASEG
;;;;;;;;;;;;;;;;; приглашение на ввод первого числа ;;;;;;;;;;;;;;
SEN_1    db 0Ah,0Dh,'1st NUM:$'
;;;;;;;;;;;;;;;;; приглашение на ввод второго числа ;;;;;;;;;;;;;;
SEN_2    db 0Ah,0Dh,'2nd NUM:$'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MINUS1   db 0
MINUS2   db 0
RESULT   db 0
BUF_1    db 11       
LEN_1    db ?                       ; длина 1 строки
Opnd1    db 12 dup( ? )             ; буфер 1 числа
BUF_2    db 11
LEN_2    db ?                       ; длина 2 строки
Opnd2    db 12 dup( ? )             ; буфер 2 числа
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;; приглашение на вывод результата ;;;;;;;;;;;;;;;;
ResT    db 0Ah,0Dh,'Differ: '
Res     db 12 dup(' '),'$' ; буфер результата
;;;;;;;;;;;;;;;;; запрос о продолжении работы ;;;;;;;;;;;;;;;;;;;;
AskCont db 0Ah,0Dh
        db 'Shut down - Esc, Continue - any key'
        db '$'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        CODESEG
        STARTUPCODE
        PUSH    DS
        POP     ES                  ; ES <- DS
 
BEGIN:
;;;;;;;; ввод первого числа ;;;;;;;;;;;;;;;;;;;;;
B1:     
        LEA     DX, SEN_1           ; в DX занести адрес строки
        MOV     AH, 09h             ; в АН занести номер функции (вывод)
        INT     21h                 ; вызов прерывания 
        LEA     DX, BUF_1           ; в DX занести адрес строки
        MOV     AH, 0Ah             ; в АН занести номер функции (ввод)
        INT     21h                 ; вызов прерывания
        CMP     LEN_1, 0            ; сравниваем длину строки с нулем
        JE      B1                  ; если равен нулю, то вводим заново
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;       
;;; проверка 0-9 и очистка старшей тетрады ;;;;;;
        LEA     BX, Opnd1           ; загружаем введённую строку в рег-р ВХ
        XOR     CX, CX              ; обнулить регистр CX
        MOV     CL, LEN_1           ; в СL занести длину строки
        XOR     SI, SI              ; обнулить регистр SI       
T1:   ;;;;; начало цикла ;;;;;;;;;  
        MOV     AL, [BX][SI]
        CMP     AL, '-'
        JZ      NEGA1
        CMP     AL, '0'             ; сравнить с кодом нуля
        JB      B1                  ; если ниже, ошибка
        CMP     AL, '9'             ; сравнить с кодом девятки
        JA      B1                  ; если выше, ошибка
        AND     AL, 0Fh             ; обнулить старшую тетраду (АL & 0000 1111)
        MOV     [BX][SI], AL        ; занести результат в массив
        INC     SI                  ; перейти к следующему элементу
        LOOP    T1                  ; проверка на конец цикла и переход на метку
        ;;;;; конец цикла ;;;;;;;;;;
;;;;;;;;;;;;; прижать к правому краю ;;;;;;;;;;;
        MOV     CL, LEN_1           ; в CL занести длину строки
        CMP     CL, 10              ; сравнить СL с 10
        JE      E1                  ; если равно, то перейти на метку
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     DI, 9               ; в DI занести смещение (адрес конца строки)
        MOV     SI, CX              ; в SI занести смещение (адрес первого разряда + 1)
        DEC     SI                  ; уменьшить SI на единицу       
P1:      ;;;; начало цикла ;;;;;;;
        MOV     AL, [BX][SI]        ; в АL занести элемент массива
        MOV     [BX][DI], AL        ; поместить AL в правую часть массива
        DEC     DI                  ; уменьшить DI на единицу
        DEC     SI                  ; уменьшить SI на единицу
        LOOP    P1                  ; проверить на конец цикла и перейти по метке
        ;;;; конец цикла ;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;; обнулить лишнее ;;;;;;;;;;;;;;;;;;;;;;;
        XOR     DI, DI              ; обнулить регистр DI
        MOV     CL, 10              ; занести в регистр СL значение 10
        SUB     CL, LEN_1           ; отнять от CL длину строки
N1:     ;;;;; начало цикла ;;;;;;
        MOV     byte ptr [BX][DI], 0; заменить на нуль
        INC     DI                  ; увеличить DI на единицу
        LOOP    N1                  ; проверить на конец цикла и перейти по метке
        ;;;;; конец цикла ;;;;;;;
        JMP E1
;;;;;;;;;;;; учитываем минус ;;;;;;;;;;;;;;;;;;;
NEGA1:
        ADD MINUS1, 1
        INC SI
        LOOP T1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
E1:
;;;;;;;;;;; ввод второго числа ;;;;;;;;;;;;;;;;;
B2:     LEA     DX, SEN_2           ; в DX занести адрес строки
        MOV     AH, 09h             ; в АН занести номер функции (вывод)
        INT     21h                 ; вызов прерывания
        LEA     DX, BUF_2           ; в DX занести адрес строки
        MOV     AH, 0Ah             ; в АН занести номер функции (ввод)
        INT     21h                 ; вызов прерывания
        CMP     LEN_2, 0            ; сравниваем длину строки с нулем
        JE      B2                  ; если равен нулю, то вводим заново
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;; проверка 0-9 и очистка старшей тетерады ;
        LEA     BX, Opnd2
        XOR     CX, CX              ; обнулить регистр CX
        MOV     CL, LEN_2           ; в СL занести длину строки
        XOR     SI, SI              ; обнулить регистр SI
T2:     
        MOV     AL, [BX][SI]
        CMP     AL, '-'
        JZ      NEGA2
        CMP     AL, '0'             ; сравнить с кодом нуля
        JB      B2                  ; если ниже, ошибка 
        CMP     AL, '9'             ; сравнить с кодом девятки
        JA      B2                  ; если выше, ошибка
        AND     AL, 0Fh             ; обнулить старшую тетраду (АL & 0000 1111)
        MOV     [BX][SI], AL        ; занести результат в массив
        INC     SI                  ; перейти к следующему элементу
        LOOP    T2                  ; проверка на конец цикла и переход на метку
        ;;;;; конец цикла ;;;;;;;;;;        
;;;;;;;;;;;;; прижать к правому краю ;;;;;;;;;;;
        MOV     CL, LEN_2           ; в CL занести длину строки
        CMP     CL, 10              ; сравнить СL с 10
        JE      CHECKPOINT          ; если равно, то перейти на метку 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;        
        MOV     DI, 9               ; в DI занести смещение (адрес конца строки)
        MOV     SI, CX              ; в SI занести смещение (адрес первого разряда + 1)
        DEC     SI                  ; уменьшить SI на единицу
P2:     ;;;; начало цикла ;;;;;;;
        MOV     AL, [BX][SI]        ; в АL занести элемент массива
        MOV     [BX][DI], AL        ; поместить AL в правую часть массива
        DEC     DI                  ; уменьшить DI на единицу
        DEC     SI                  ; уменьшить SI на единицу
        LOOP    P2                  ; проверить на конец цикла и перейти по метке
;;;; конец цикла ;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;; обнулить лишнее ;;;;;;;;;;;;;;;;;;;;;;;
        XOR     DI, DI              ; обнулить регистр DI
        MOV     CL, 10              ; занести в регистр СL значение 10
        SUB     CL, LEN_2           ; отнять от CL длину строки
N2:     ;;;;; начало цикла ;;;;;; 
        MOV     byte ptr [BX][DI], 0; заменить на нуль
        INC     DI                  ; увеличить DI на единицу
        LOOP    N2                  ; проверить на конец цикла и перейти по метке
        ;;;;; конец цикла ;;;;;;;
        JMP CHECKPOINT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;; учитываем минус ;;;;;;;;;;;;;;;;;;;
NEGA2:
        ADD MINUS2, 1
        INC SI
        LOOP T2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;; Определяем операцию с учётом минуса ;;;;;;
CHECKPOINT:
        MOV  BL, MINUS1
        MOV  AL, MINUS2
        CMP  BL, 0
        JNZ  CHECK2
        CHECK1:
            CMP AL, 0
            JZ  SUBM1
            JNZ ADDI
        CHECK2:
            CMP AL, 0
            JZ  ADDI
            JNZ SUBM2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SUBM1:;;;;; Вычитание чисел (1 - 2) ;;;;;;;;;;;;;
        MOV     CX, 10              ; установить счетчик
        CLC
        LEA     SI, Opnd1+9         ; в SI занести адрес массива
        LEA     DI, Opnd2+9         ; в DI занести адрес массива
        LEA     BX, Res+10          ; в ВХ занести адрес массива
A1:     ;;;;;; начало цикла ;;;;;
        MOV     AL, [SI]            ; в АL занести текущий элемент
        SBB     AL, [DI]            ; вычитание
        AAS                         ; произвести десятичную коррекцию вычитания
        MOV     [BX], AL
        DEC     SI                  ; уменьшить SI на единицу
        DEC     DI                  ; уменьшить DI на единицу
        DEC     BX                  ; уменьшить BX на единицу
        LOOP    A1                  ; проверка на конец цикла и переход по метке
        MOV     AL, 0
        ADC     AL, 0
        MOV     [BX], AL   
;;;;;;;;Преобразование результата в ASCII;;;;;;;;;
        MOV     CX, 11
        JMP ENT
SUBM2:;;;;; Вычитание чисел (2 - 1) ;;;;;;;;;;;;;
        MOV     CX, 10              ; установить счетчик
        CLC
        LEA     SI, Opnd1+9         ; в SI занести адрес массива
        LEA     DI, Opnd2+9         ; в DI занести адрес массива
        LEA     BX, Res+10          ; в ВХ занести адрес массива
A2:     ;;;;;; начало цикла ;;;;;
        MOV     AL, [DI]            ; в АL занести текущий элемент
        SBB     AL, [SI]            ; вычитание
        AAS                         ; произвести десятичную коррекцию вычитания
        MOV     [BX], AL
        DEC     SI                  ; уменьшить SI на единицу
        DEC     DI                  ; уменьшить DI на единицу
        DEC     BX                  ; уменьшить BX на единицу
        LOOP    A2                  ; проверка на конец цикла и переход по метке
        MOV     AL, 0
        ADC     AL, 0
        MOV     [BX], AL   
;;;;;;;;Преобразование результата в ASCII;;;;;;;;;
        MOV     CX, 11
        JMP ENT
ADDI:;;;;;; Сложение чисел ;;;;;;;;;;;;;;;;;;;;;
        MOV     CX, 10              ; установить счетчик
        CLC
        LEA     SI, Opnd1+9         ; в SI занести адрес массива
        LEA     DI, Opnd2+9         ; в DI занести адрес массива
        LEA     BX, Res+10          ; в ВХ занести адрес массива
A3:     ;;;;;; начало цикла ;;;;;
        MOV     AL, [SI]            ; в АL занести текущий элемент
        ADC     AL, [DI]            ; вычитание
        AAA                         ; произвести десятичную коррекцию сложения
        MOV     [BX], AL
        DEC     SI                  ; уменьшить SI на единицу
        DEC     DI                  ; уменьшить DI на единицу
        DEC     BX                  ; уменьшить BX на единицу
        LOOP    A3                  ; проверка на конец цикла и переход по метке
        MOV     AL, 0
        ADC     AL, 0
        MOV     [BX], AL   
;;;;;;;;Преобразование результата в ASCII;;;;;;;;;
        MOV     CX, 11
;;;;; запрос на продолжение работы ;;;;;;;;;;;;;;;
ENT:
        OR      byte ptr [BX], 30h
        INC     BX                  ; увеличить BX на единицу
        LOOP    A2                  ; проверка на конец цикла и переход по метке
;;;;;;;;;;;;;;; Вывод результата ;;;;;;;;;;;;;;;;;
        LEA     DX, ResT            ; в DX занести адрес строки
        MOV     AH, 09h             ; в АН занести номер функции (вывод)
        INT     21h                 ; вызвать прерывание
        LEA     DX, AskCont         ; в DX занести адрес строки
        MOV     AH, 09h             ; в АH занести номер функции (вывод)
        INT     21h                 ; вызвать прерывание
        
        MOV     AH, 08h             ; в АН занести номер функции (ввод)
        INT     21h                 ; вызвать прерывание
        CMP     AL, 27              ; проверить на нажатие Esc
        JE      QUIT                ; была нажата Esc, завершить программу
        JMP     BEGIN               ; переход в начало программы
 
;Конец работы
QUIT:   EXITCODE  0                 ; вернуть в ОС код 0
        END                         ; конец программы
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.04.2018, 13:12
Ответы с готовыми решениями:

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

Калькулятор, выполняющий действия + – (в упакованном BCD-формате)
Напишите программу – калькулятор выполняющую действия + –, внутреннее...

Сложение двух BCD чисел
При проверке программы (через Тасм в проге фар, выдаёт ошибку в выводе...

Сложение упакованных BCD чисел
Мне требуется сложить два упакованных BCD числа: 5643 и 9127 Вот что я...

Сложение двух BCD чисел
Помогите с задачей, нужно чтобы вводилось двухзначное число, я сделал что...

10
ФедосеевПавел
Модератор
3661 / 2030 / 842
Регистрация: 01.02.2015
Сообщений: 6,764
19.04.2018, 21:03 2
Посмотрите в теме
BCD (сложение и вычитание)
При отрицательном результате проводится преобразование всех байтов результата.

Добавлено через 8 минут
И ещё здесь
http://www.i-assembler.ru/25/Lesson/Lesson08/Les_08.htm
0
cinekst_207
0 / 0 / 5
Регистрация: 25.03.2018
Сообщений: 50
20.04.2018, 20:48  [ТС] 3
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
;Сложение
 
mov CX, 10
 
clc
 
lea SI, Opnd1+9
 
lea DI, Opnd2+9
 
lea BX, Res+10
 
A1: mov AL, [SI]
 
adc AL, [DI]
 
aaa
 
mov [BX], AL
 
dec SI
 
dec DI
 
dec BX
 
loop A1
 
mov AL, 0
 
adc AL, 0
 
mov [BX], AL
Вот по данному примеру замутил сложение(если 1е число отрицательное, а второе пол., то должно при вычитании сложиться всё со знаком минус(-x-y = -(x+y)\или если 1е пол., а 2е отриц. тоже: x-(-y)=x+y) Но у меня выводит вот что:
0
Миниатюры
Вычитание чисел в формате BCD  
ФедосеевПавел
Модератор
3661 / 2030 / 842
Регистрация: 01.02.2015
Сообщений: 6,764
20.04.2018, 20:59 4
Мне кажется, что у чисел в формате BCD нет места для хранения знака. Это приводит к тому, что все они являются неотрицательными, беззнаковыми.

Т.е. нужно выделить отдельный байт для хранения знака. А при операциях учитывать этот знак.
Также, в примерах по ссылке был фрагмент кода, в котором проверялся знак результата и при отрицательном значении выполнялось преобразование всего многозначного числа.
0
cinekst_207
0 / 0 / 5
Регистрация: 25.03.2018
Сообщений: 50
20.04.2018, 22:03  [ТС] 5
Так я знак в виде флага сохраняю и в CHECK проверяю какие знаки где находятся. У меня само сложение неправильное. 123+321=444, а у меня выдаёт 19999999198, а должно 00000000444. Код которыё я скинул(сложение) рабочий и нормально складывает неупакованные числа, я его, грубо говоря скопипастил в мой код, и тут перестало работать, почему? Не понимаю, вот и спрашиваю . Я донёс суть вопроса ? XD
0
ФедосеевПавел
Модератор
3661 / 2030 / 842
Регистрация: 01.02.2015
Сообщений: 6,764
20.04.2018, 22:10 6
Подозреваю, что в "источнике вдохновения кодом" порядок старших и младших байт разнится с таковым в вашей программе. Отсюда и иной ответ.

Добавлено через 1 минуту
Имеется в виду порядок старшинства байт во многобайтовом числе.
0
cinekst_207
0 / 0 / 5
Регистрация: 25.03.2018
Сообщений: 50
20.04.2018, 22:14  [ТС] 7
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
model SMALL
 
stack 100h
 
dataseg
 
Ask1 db 0Ah,0Dh,'Введите первое слагаемое (не более 10 цифр):$'
 
Ask2 db 0Ah,0Dh,'Введите второе слагаемое (не более 10 цифр):$'
 
Buf1 db 11
 
Len1 db ?
 
Opnd1 db 12 dup( ? )
 
Buf2 db 11
 
Len2 db ?
 
Opnd2 db 12 dup( ? )
 
ResTdb 0Ah,0Dh,'Сумма'
 
Res db 12 dup(' '),'$'
 
AskContdb 0Ah,0Dh
 
db'Завершитьработу- Esc, продолжить – Любая клавиша'
 
db '$'
 
codeseg
 
startupcode
 
push DS
 
pop ES ; ES <- DS
 
BEGIN:
 
;Ввод первого слагаемого
 
B1: leaDX, Ask1
 
mov AH, 09h
 
int 21h
 
lea DX, Buf1
 
mov AH, 0Ah
 
int 21h
 
cmp Len1, 0
 
jeB1
 
;проверка 0-9 и очистка старш.тетрады
 
lea BX, Opnd1
 
xor CX, CX
 
mov CL, Len1
 
xor SI, SI
 
T1: mov AL, [BX][SI]
 
cmp AL, '0'
 
jbB1 ; ошибка
 
cmp AL, '9'
 
jaB1 ; ошибка
 
and AL, 0Fh
 
mov [BX][SI], AL
 
incSI
 
loopT1
 
;прижать к правому краю
 
mov CL, Len1
 
cmp CL, 10
 
je E1
 
mov DI, 9
 
mov SI, CX
 
dec SI
 
P1: mov AL, [BX][SI]
 
mov [BX][DI], AL
 
dec DI
 
dec SI
 
loopP1
 
;обнулитьлишнее
 
xor DI, DI
 
mov CL, 10
 
sub CL, Len1
 
N1: mov byte ptr [BX][DI], 0
 
inc DI
 
loopN1
 
E1:
 
;Ввод второго слагаемого
 
B2: leaDX, Ask2
 
mov AH, 09h
 
int 21h
 
lea DX, Buf2
 
mov AH, 0Ah
 
int 21h
 
cmp Len2, 0
 
jeB2
 
;проверка 0-9 и очистка старш.тетрады
 
lea BX, Opnd2
 
xor CX, CX
 
mov CL, Len2
 
xor SI, SI
 
T2: mov AL, [BX][SI]
 
cmp AL, '0'
 
jbB2 ; ошибка
 
cmp AL, '9'
 
jaB2 ; ошибка
 
and AL, 0Fh
 
mov [BX][SI], AL
 
incSI
 
loopT2
 
;прижать к правому краю
 
mov CL, Len2
 
cmp CL, 10
 
je E2
 
mov DI, 9
 
mov SI, CX
 
dec SI
 
P2: mov AL, [BX][SI]
 
mov [BX][DI], AL
 
dec DI
 
dec SI
 
loopP2
 
;обнулитьлишнее
 
xor DI, DI
 
mov CL, 10
 
sub CL, Len2
 
N2: mov byte ptr [BX][DI], 0
 
inc DI
 
loopN2
 
E2:
 
;Сложение
 
mov CX, 10
 
clc
 
lea SI, Opnd1+9
 
lea DI, Opnd2+9
 
lea BX, Res+10
 
A1: mov AL, [SI]
 
adc AL, [DI]
 
aaa
 
mov [BX], AL
 
dec SI
 
dec DI
 
dec BX
 
loop A1
 
mov AL, 0
 
adc AL, 0
 
mov [BX], AL
 
;Преобразование результата в ASCII
 
movCX, 11
 
A2: or byte ptr [BX], 30h
 
incBX
 
loopA2
 
;Вывод результата
 
lea DX, ResT
 
mov AH, 09h
 
int 21h
 
;Запрос на продолжение работы
 
lea DX, AskCont
 
mov AH, 09h
 
int 21h
 
mov AH, 08h
 
int 21h
 
cmp AL, 27 ;ESC
 
je QUIT
 
jmp BEGIN
 
;Конец работы
 
QUIT: exitcode 0
 
end
Присвоение и т.д. всё идентично моему началу . Я вот уже 2 дня голову ломаю, что не так. Может минус оно не обнуляет и как-то криво записывает. Хотя тогда бы и с 2мя минусами бы не работало.... Не понимаю
0
ФедосеевПавел
Модератор
3661 / 2030 / 842
Регистрация: 01.02.2015
Сообщений: 6,764
20.04.2018, 22:22 8
Сейчас уже плохо соображаю. Завтра посмотрю.
0
cinekst_207
0 / 0 / 5
Регистрация: 25.03.2018
Сообщений: 50
23.04.2018, 19:22  [ТС] 9
Лучший ответ Сообщение было отмечено ФедосеевПавел как решение

Решение

Я хз, просто беру и этот же код отдельно вставляю, и всё работает XD ошибок даже по обращению нет

Добавлено через 21 час 46 минут
Я нашёл проблему. Крч у меня в SI смещение сохраняется, а нужно, чтобы при минусе, смещение +1 было
0
ФедосеевПавел
Модератор
3661 / 2030 / 842
Регистрация: 01.02.2015
Сообщений: 6,764
23.04.2018, 19:47 10
А я знал, что спешить не нужно!

Если не трудно - опубликуйте итоговое решение.
0
cinekst_207
0 / 0 / 5
Регистрация: 25.03.2018
Сообщений: 50
23.04.2018, 20:50  [ТС] 11
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
.model  SMALL
        STACK  100h
        DATASEG
;;;;;;;;;;;;;;;;; приглашение на ввод первого числа ;;;;;;;;;;;;;;
SEN_1    db 0Ah,0Dh,'1st NUM:$'
;;;;;;;;;;;;;;;;; приглашение на ввод второго числа ;;;;;;;;;;;;;;
SEN_2    db 0Ah,0Dh,'2nd NUM:$'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MINUS1   db 0
MINUS2   db 0
RESULT   db 0
BUF_1    db 11       
LEN_1    db ?                       ; длина 1 строки
Opnd1    db 12 dup( ? )             ; буфер 1 числа
BUF_2    db 11
LEN_2    db ?                       ; длина 2 строки
Opnd2    db 12 dup( ? )             ; буфер 2 числа
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;; приглашение на вывод результата ;;;;;;;;;;;;;;;;
ResT    db 0Ah,0Dh,'Differ: '
Res     db 12 dup(' '),'$' ; буфер результата
;;;;;;;;;;;;;;;;; запрос о продолжении работы ;;;;;;;;;;;;;;;;;;;;
AskCont db 0Ah,0Dh
        db 'Shut down - Esc, Continue - any key'
        db '$'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        CODESEG
        STARTUPCODE
        PUSH    DS
        POP     ES                  ; ES <- DS
 
BEGIN:
;;;;;;;; ввод первого числа ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
B1:     
        LEA     DX, SEN_1           ; в DX занести адрес строки
        MOV     AH, 09h             ; в АН занести номер функции (вывод)
        INT     21h                 ; вызов прерывания 
        LEA     DX, BUF_1           ; в DX занести адрес строки
        MOV     AH, 0Ah             ; в АН занести номер функции (ввод)
        INT     21h                 ; вызов прерывания
        CMP     LEN_1, 0            ; сравниваем длину строки с нулем
        JE      B1                  ; если равен нулю, то вводим заново
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; проверка 0-9 и очистка старшей тетрады ;;;;;;;;;;;;;;;;;;;;;;;
        LEA     BX, Opnd1           ; загружаем введённую строку в рег-р ВХ
        XOR     CX, CX              ; обнулить регистр CX
        MOV     CL, LEN_1           ; в СL занести длину строки
        XOR     SI, SI              ; обнулить регистр SI       
T1:   ;;;;; начало цикла ;;;;;;;;;  
        MOV     AL, [BX][SI]
        CMP     AL, '-'             ; сравнить с кодом минуса
        JZ      NEGA1               ; если да, то переход по метке
        CMP     AL, '0'             ; сравнить с кодом нуля
        JB      B1                  ; если ниже, ошибка
        CMP     AL, '9'             ; сравнить с кодом девятки
        JA      B1                  ; если выше, ошибка
        AND     AL, 0Fh             ; обнулить старшую тетраду (АL & 0000 1111)
        MOV     [BX][SI], AL        ; занести результат в массив
        INC     SI                  ; перейти к следующему элементу
        LOOP    T1                  ; проверка на конец цикла и переход на метку
        ;;;;; конец цикла ;;;;;;;;;;
;;;;;;;;;;;;; прижать к правому краю ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     CL, LEN_1           ; в CL занести длину строки
        CMP     CL, 10              ; сравнить СL с 10
        JE      E1                  ; если равно, то перейти на метку
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     DI, 9               ; в DI занести смещение (адрес конца строки)
        CMP     MINUS1, 1           ; есть-ли минус в числе
        JB NO1                      ; если нет то переход по метке NO
        YES1:                       ; иначе число имеет знак минус
            ADD     CX, 1           ; прибавляем к CX 1(т.к. минус первый знак)
            MOV     SI, CX          ; в SI занести смещение (адрес первого разряда + 1)
            DEC     SI              ; уменьшить SI на единицу 
            JMP     P1
        NO1:
            MOV     SI, CX          ; в SI занести смещение (адрес первого разряда + 1)
            DEC     SI              ; уменьшить SI на единицу  
P1:      ;;;; начало цикла ;;;;;;;
        MOV     AL, [BX][SI]        ; в АL занести элемент массива
        MOV     [BX][DI], AL        ; поместить AL в правую часть массива
        DEC     DI                  ; уменьшить DI на единицу
        DEC     SI                  ; уменьшить SI на единицу
        LOOP    P1                  ; проверить на конец цикла и перейти по метке
        ;;;; конец цикла ;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;; обнулить лишнее ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        XOR     DI, DI              ; обнулить регистр DI
        MOV     CL, 10              ; занести в регистр СL значение 10
        SUB     CL, LEN_1           ; отнять от CL длину строки
N1:     ;;;;; начало цикла ;;;;;;
        MOV     byte ptr [BX][DI], 0; заменить на нуль
        INC     DI                  ; увеличить DI на единицу
        LOOP    N1                  ; проверить на конец цикла и перейти по метке
        ;;;;; конец цикла ;;;;;;;
        JMP E1
;;;;;;;;;;;; учитываем минус ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NEGA1:
        ADD MINUS1, 1               ; прибавим к операнду MINUS1 1
        SUB CL, 1                   ; уменьшаем CL
        SUB LEN_1, 1                ; уменьшаем длину строки
        INC SI                      ; увеличить SI на единицу
        JMP T1                      ; перейти по метке
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
E1:
;;;;;;;;;;; ввод второго числа ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
B2:     LEA     DX, SEN_2           ; в DX занести адрес строки
        MOV     AH, 09h             ; в АН занести номер функции (вывод)
        INT     21h                 ; вызов прерывания
        LEA     DX, BUF_2           ; в DX занести адрес строки
        MOV     AH, 0Ah             ; в АН занести номер функции (ввод)
        INT     21h                 ; вызов прерывания
        CMP     LEN_2, 0            ; сравниваем длину строки с нулем
        JE      B2                  ; если равен нулю, то вводим заново
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;; проверка 0-9 и очистка старшей тетерады ;;;;;;;;;;;;;;;;;;;
        LEA     BX, Opnd2
        XOR     CX, CX              ; обнулить регистр CX
        MOV     CL, LEN_2           ; в СL занести длину строки
        XOR     SI, SI              ; обнулить регистр SI
T2:     
        MOV     AL, [BX][SI]
        CMP     AL, '-'             ; сравнить с кодом минуса
        JZ      NEGA2               ; если да, то переход по метке
        CMP     AL, '0'             ; сравнить с кодом нуля
        JB      B2                  ; если ниже, ошибка 
        CMP     AL, '9'             ; сравнить с кодом девятки
        JA      B2                  ; если выше, ошибка
        AND     AL, 0Fh             ; обнулить старшую тетраду (АL & 0000 1111)
        MOV     [BX][SI], AL        ; занести результат в массив
        INC     SI                  ; перейти к следующему элементу
        LOOP    T2                  ; проверка на конец цикла и переход на метку
        ;;;;; конец цикла ;;;;;;;;;;        
;;;;;;;;;;;;; прижать к правому краю ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     CL, LEN_2           ; в CL занести длину строки
        CMP     CL, 10              ; сравнить СL с 10
        JE      CHECKPOINT          ; если равно, то перейти на метку 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
        MOV     CL, LEN_1           ; в CL занести длину строки
        CMP     CL, 10              ; сравнить СL с 10
        JE      E1                  ; если равно, то перейти на метку
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     DI, 9               ; в DI занести смещение (адрес конца строки)
        CMP     MINUS2, 1           ; есть-ли минус в числе
        JB NO2                      ; если нет то переход по метке NO
        YES2:                       ; иначе число имеет знак минус
            ADD     CX, 1           ; прибавляем к CX 1(т.к. минус первый знак)
            MOV     SI, CX          ; в SI занести смещение (адрес первого разряда + 1)
            DEC     SI              ; уменьшить SI на единицу 
            JMP     P2
        NO2:
            MOV     SI, CX          ; в SI занести смещение (адрес первого разряда + 1)
            DEC     SI              ; уменьшить SI на единицу 
P2:     ;;;; начало цикла ;;;;;;;
        MOV     AL, [BX][SI]        ; в АL занести элемент массива
        MOV     [BX][DI], AL        ; поместить AL в правую часть массива
        DEC     DI                  ; уменьшить DI на единицу
        DEC     SI                  ; уменьшить SI на единицу
        LOOP    P2                  ; проверить на конец цикла и перейти по метке
;;;; конец цикла ;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;; обнулить лишнее ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        XOR     DI, DI              ; обнулить регистр DI
        MOV     CL, 10              ; занести в регистр СL значение 10
        SUB     CL, LEN_2           ; отнять от CL длину строки
N2:     ;;;;; начало цикла ;;;;;; 
        MOV     byte ptr [BX][DI], 0; заменить на нуль
        INC     DI                  ; увеличить DI на единицу
        LOOP    N2                  ; проверить на конец цикла и перейти по метке
        ;;;;; конец цикла ;;;;;;;
        JMP CHECKPOINT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;; учитываем минус ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NEGA2:
        ADD  MINUS2, 1              ; прибавим к операнду MINUS2 1
        SUB  CL, 1                  ; уменьшаем длину строки
        SUB LEN_2, 1                ; уменьшаем длину строки
        INC  SI                     ; увеличить SI на единицу
        JMP T2                      ; перейти по метке
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;; Определяем операцию с учётом минуса ;;;;;;;;;;;;;;;;;;;;;;;;
CHECKPOINT:
        MOV  BL, MINUS1             ; заносим указатель на минус в рег-р ВL
        MOV  AL, MINUS2             ; заносим указатель на минус в рег-р AL
        CMP  BL, 0                  ; сравниваем BL с 0
        JNZ  CHECK2                 ; если они не равны, то переход на метку ЧЕК2
;;;;;; Если первый операнд без знака минус ;;;;;;;;;;;;;;;;;;;;;;;
        CHECK1:
            CMP AL, 0               ; сравниваем AL с 0
            JZ  SUBM1               ; если 0, то вычитание операндов (1 - 2)
            JNZ ADDI                ; если же 1, то сложение операндов
;;;;;; Если первый операнд со знаком минус ;;;;;;;;;;;;;;;;;;;;;;;
        CHECK2:
            CMP AL, 0               ; сравниваем AL c 0
            JZ  ADDI                ; если 0, то сложение операндов
            JNZ SUBM2               ; если же 1, то вычитание операндов (2 - 1)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SUBM1:;;;;; Вычитание чисел (1 - 2) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     CX, 10              ; установить счетчик
        CLC
        LEA     SI, Opnd1+9         ; в SI занести адрес массива
        LEA     DI, Opnd2+9         ; в DI занести адрес массива
        LEA     BX, Res+10          ; в ВХ занести адрес массива
A1:     ;;;;;; начало цикла ;;;;;
        MOV     AL, [SI]            ; в АL занести текущий элемент
        SBB     AL, [DI]            ; вычитание
        AAS                         ; произвести десятичную коррекцию вычитания
        MOV     [BX], AL
        DEC     SI                  ; уменьшить SI на единицу
        DEC     DI                  ; уменьшить DI на единицу
        DEC     BX                  ; уменьшить BX на единицу
        LOOP    A1                  ; проверка на конец цикла и переход по метке
        MOV     AL, 0
        ADC     AL, 0
        MOV     [BX], AL   
;;;;;;;;Преобразование результата в ASCII;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     CX, 11
        JMP ENT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SUBM2:;;;;; Вычитание чисел (2 - 1) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     CX, 10              ; установить счетчик
        CLC
        LEA     SI, Opnd1+9         ; в SI занести адрес массива
        LEA     DI, Opnd2+9         ; в DI занести адрес массива
        LEA     BX, Res+10          ; в ВХ занести адрес массива
A2:     ;;;;;; начало цикла ;;;;;
        MOV     AL, [DI]            ; в АL занести текущий элемент
        SBB     AL, [SI]            ; вычитание
        AAS                         ; произвести десятичную коррекцию вычитания
        MOV     [BX], AL
        DEC     SI                  ; уменьшить SI на единицу
        DEC     DI                  ; уменьшить DI на единицу
        DEC     BX                  ; уменьшить BX на единицу
        LOOP    A2                  ; проверка на конец цикла и переход по метке
        MOV     AL, 0
        ADC     AL, 0
        MOV     [BX], AL   
;;;;;;;;Преобразование результата в ASCII;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     CX, 11
        JMP ENT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDI:;;;;;; Сложение чисел ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     CX, 10              ; установить счетчик
        CLC
        LEA     SI, Opnd1+9         ; в SI занести адрес массива
        LEA     DI, Opnd2+9         ; в DI занести адрес массива
        LEA     BX, Res+10          ; в ВХ занести адрес массива
A3:     ;;;;;; начало цикла ;;;;;
        MOV     AL, [SI]            ; в АL занести текущий элемент
        ADC     AL, [DI]            ; вычитание
        AAA                         ; произвести десятичную коррекцию сложения
        MOV     [BX], AL
        DEC     SI                  ; уменьшить SI на единицу
        DEC     DI                  ; уменьшить DI на единицу
        DEC     BX                  ; уменьшить BX на единицу
        LOOP    A3                  ; проверка на конец цикла и переход по метке
        MOV     AL, 0
        ADC     AL, 0
        MOV     [BX], AL   
;;;;;;;;Преобразование результата в ASCII;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     CX, 11
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;; запрос на продолжение работы ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ENT:
        OR      byte ptr [BX], 30h
        INC     BX                  ; увеличить BX на единицу
        LOOP    ENT                 ; проверка на конец цикла и переход по метке
;;;;;;;;;;;;;;; Вывод результата ;;;;;;;;;;;;;;;;;
        LEA     DX, ResT            ; в DX занести адрес строки
        MOV     AH, 09h             ; в АН занести номер функции (вывод)
        INT     21h                 ; вызвать прерывание
        LEA     DX, AskCont         ; в DX занести адрес строки
        MOV     AH, 09h             ; в АH занести номер функции (вывод)
        INT     21h                 ; вызвать прерывание
        
        MOV     AH, 08h             ; в АН занести номер функции (ввод)
        INT     21h                 ; вызвать прерывание
        CMP     AL, 27              ; проверить на нажатие Esc
        JE      QUIT                ; была нажата Esc, завершить программу
        JMP     BEGIN               ; переход в начало программы
 
;Конец работы
QUIT:   EXITCODE  0                 ; вернуть в ОС код 0
        END                         ; конец программы
Последняя проблема осталась XD, -12345-123=-12468, а у меня 12775 в проге -_-

Добавлено через 6 минут
а при 12345 и -123 = 12777 капец, ну что не так

Добавлено через 40 минут
Запутался уже в этой проге, туча перемен в коде, уже не понимаю что менять. Я так понимаю, ошибка в SI и в DI, но как с ними иначе работать, если знак минуса надо учитывать =/
0
23.04.2018, 20:50
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.04.2018, 20:50

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

Просуммировать два массива двоично-десятичных (BCD) четырехзначных чисел
Здравствуйте! У меня несколько команды не хватает. Или что то я пишу не ...

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


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

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

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