0 / 0 / 0
Регистрация: 10.10.2016
Сообщений: 34
1
emu8086

Перевести римские цифры в арабские

18.09.2019, 06:01. Показов 2949. Ответов 9

Только начинаю изучать ассемблер и появилась сложность в написание программы. Необходима ввести с клавиатуры римские числа, произвести с ними арифметические действия (сложение, вычитание и умножение) и вывести на экран ответ в 10м счислении (арабские цифры). Так же нужно проверить строку на ошибки ввода (повторения некоторых символов рядом и на наличие других букв, цифр и т.д.).
Разобралась более ли менее с арифметикой, но сама запись и проверка вызывает большие затруднение. Помогите, пожалуйста.
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.09.2019, 06:01
Ответы с готовыми решениями:

Перевод числа в римские цифры
Только - только начали проходить assembler. Задали написать программу, но я не представляю как...

Перевод числа в римские цифры
Нужно написать программу, которая переводит число в римские цифры. Программа должна содержать...

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

Нужно перевести римские цифры в арабские
Дан текст из заглавных латинских букв, за которым следует пробел. Определить, является ли этот...

9
0 / 0 / 0
Регистрация: 10.10.2016
Сообщений: 34
18.09.2019, 13:48  [ТС] 2
Тут нужна конкретно помощь в сопоставлении определенной букве (из римских чисел) к соответствующей цифре(в 10ке), чтобы вывести на экран. Ну и при возможности, объяснить, как сделать правильно проверку на эту часть кода. Что касаемо задания в целом, то часть его уже сделана (арифметика), вся сложность с римскими числами
0
1577 / 810 / 146
Регистрация: 13.06.2015
Сообщений: 3,206
18.09.2019, 14:22 3
MollyLu, для начала вам надо определиться с двумя моментами:
1) В простой форме возможен ввод римских чисел до 3999 включительно.
2) При записи может использоваться как принцип сложения (VIIII), так и принцип вычитания (IX). Реализовать второй (либо оба одновременно) в разы сложнее, чем первый.
Для реализации принципа сложения достаточно сравнивать символы командой cmp и просто прибавлять число, соответствующее символу. Кроме того, надо проверять, чтобы цифры шли по невозрастанию:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mov Prev,1000
M:lobsb          ; цикл сканирования строки, загрузка очередного символа
cmp al,'I'       ; сравнения символов
je IsI
cmp al,'V'
je IsV
....
jmp Err          ; это не цифра - некорректная строка
IsI:mov dx,1     ; преобразование в цифру
jmp Next
IsV:mov dx,5
jmp Next
......
IsM:mov dx,1000
jmp Next
Next:
cmp Prev,dx      ; сравнение с предыдущей цифрой
jb Err           ; если предыдущая меньше - ошибка
add Res,dx       ; инкремент результата
Next:loop M      ; переход к следующему символу
Err: ......      ; обработка ошибки
Можно использовать гораздо более эффективный подход с табличным преобразованием xlat, но он потребует существенных умственных и физических усилий.
1
Ушел с форума
Автор FAQ
15029 / 7224 / 898
Регистрация: 11.11.2010
Сообщений: 12,969
18.09.2019, 17:35 4
MollyLu,
попробуй аналогичную программу написать на Паскале/Си/Бейсике и сможешь оценить сложность своей задачи, будет готова программа на Паскале/Си/Бейсике, тогда при помощи вставок на ассемблере можно будет перевести ее целиком на язык ассемблера.
Kukuxumushu,
сперва ищут в строке букву "M" (mille - тысяча), если такая буква единственная, смотрим, нет ли слева буквы "C" (centum - сотня), если есть, то у нас 900, то же самое с буквой "C" и буквой "X" ("decem" - десять), то же самое с буквой "X" и буквой "I", с буквами "D" (quingenti - 500), "L" (quinquaginta - 50), "V" (quinque - 5) возможно только сложение, а остальное ты уже описал, только я бы использовал SCASB

P.S.
MollyLu,
для начала напиши программу, которая переводит римские цифры в индийские от 1 до 39
Kukuxumushu,
если написать подпрограмму, которая корректно обработает символы I, V, X. То ее можно расширить для X, L, C, а затем для C, D, M
0
Ушел с форума
Автор FAQ
15029 / 7224 / 898
Регистрация: 11.11.2010
Сообщений: 12,969
19.09.2019, 04:05 5
поторопился, с буквами V, L, D аналогично буквам X, C, M
0
Модератор
Эксперт по электронике
7758 / 3908 / 1503
Регистрация: 01.02.2015
Сообщений: 12,061
Записей в блоге: 2
20.09.2019, 21:46 6
Вспомнил, что FPC в модуле strutils имеет функции для преобразования римских чисел.
Поискал среди исходников и нашёл.
Описание
Pascal
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
{ TryRomanToInt: try to convert a roman numeral to an integer
  Parameters:
  S: Roman numeral (like: 'MCMXXII')
  N: Integer value of S (only meaningfull if the function succeeds)
  Stricness: controls how strict the parsing of S is
    - rcsStrict:
      * Follow common subtraction rules
         - only 1 preceding subtraction character allowed: IX = 9, but IIX <> 8
         - from M you can only subtract C
         - from D you can only subtract C
         - from C you can only subtract X
         - from L you can only subtract X
         - from X you can only subtract I
         - from V you can only subtract I
      *  The numeral is parsed in "groups" (first M's, then D's etc.), the next group to be parsed
         must always be of a lower denomination than the previous one.
         Example: 'MMDCCXX' is allowed but 'MMCCXXDD' is not
      * There can only ever be 3 consecutive M's, C's, X's or I's
      * There can only ever be 1 D, 1 L and 1 V
      * After IX or IV there can be no more characters
      * Negative numbers are not supported
      // As a consequence the maximum allowed Roman numeral is MMMCMXCIX = 3999, also N can never become 0 (zero)
 
    - rcsRelaxed: Like rcsStrict but with the following exceptions:
      * An infinite number of (leading) M's is allowed
      * Up to 4 consecutive M's, C's, X's and I's are allowed
      // So this is allowed: 'MMMMMMCXIIII'  = 6124
 
    - rcsDontCare:
      * no checking on the order of "groups" is done
      * there are no restrictions on the number of consecutive chars
      * negative numbers are supported
      * an empty string as input will return True and N will be 0
      * invalid input will return false
      // for backwards comatibility: it supports rather ludicrous input like '-IIIMIII' -> -(2+(1000-1)+3)=-1004
}
Т.е. установилось три подхода к корректности "римских чисел". Строгий подход учитывает много факторов, ослабленный - на один фактор меньше, а безразличный - одно всего упрощённое правило (если следующая цифра меньше, то текущую добавляем к результату, иначе - вычитаем).

Далее в исходниках для "безразличного" варианта виден вызов RomanToIntDontCare, а для остальных длинный код со множеством проверок.

Исходный текст RomanToIntDontCare похож по смыслу на аналогичный из языка C++:
Pascal
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
function RomanToIntDontCare(const S: String): Longint;
{This was the original implementation of RomanToInt,
 it is internally used in TryRomanToInt when Strictness = rcsDontCare}
const
  RomanChars  = ['C','D','I','L','M','V','X'];
  RomanValues : array['C'..'X'] of Word
              = (100,500,0,0,0,0,1,0,0,50,1000,0,0,0,0,0,0,0,0,5,0,10);
 
var
  index, Next: Char;
  i,l: SizeInt;
  Negative: Boolean;
 
begin
  Result:=0;
  i:=0;
  Negative:=(Length(S)>0) and (S[1]='-');
  if Negative then
    inc(i);
  l:=Length(S);
  while (i<l) do
    begin
    inc(i);
    index:=UpCase(S[i]);
    if index in RomanChars then
      begin
      if Succ(i)<=l then
        Next:=UpCase(S[i+1])
      else
        Next:=#0;
      if (Next in RomanChars) and (RomanValues[index]<RomanValues[Next]) then
        begin
        inc(Result, RomanValues[Next]);
        Dec(Result, RomanValues[index]);
        inc(i);
        end
      else
        inc(Result, RomanValues[index]);
      end
    else
      begin
      Result:=0;
      Exit;
      end;
    end;
  if Negative then
    Result:=-Result;
end;
Так в этих исходниках хорошо виден алгоритм и подход к преобразованию латинской буквы в соответствующее число - при помощи массива.
Для упрощения можно опустить проверки корректности символов и преобразование к верхнему регистру.
1
0 / 0 / 0
Регистрация: 10.10.2016
Сообщений: 34
30.09.2019, 10:23  [ТС] 7
Kukuxumushu, спасибо, но что если реализовать это через двумерный массив? каждому числу римскому соответствует арабское число. И все же склоняюсь больше написать программу, где будут реализованы оба варианта, только не используя вычитания, а, например, изначально в массив ввести исключения по типу IV, IX и т.д. И вводя две строки такие через пробел, сравнивать предыдущий и последующий элемент (IV или VI) и там соответственно, плюсовать как есть. Вопрос в том, можно ли так сделать через вашу реализация, или только через двумерный массив и поиск внутри него соответствующего элемента?
Цитата Сообщение от Kukuxumushu Посмотреть сообщение
Реализовать второй (либо оба одновременно) в разы сложнее, чем первый.
Добавлено через 5 часов 14 минут
Цитата Сообщение от Kukuxumushu Посмотреть сообщение
Можно использовать гораздо более эффективный подход с табличным преобразованием xlat, но он потребует существенных умственных и физических усилий.
чувствую, что именно это и нужно в данной работе...
0
Модератор
Эксперт по электронике
7758 / 3908 / 1503
Регистрация: 01.02.2015
Сообщений: 12,061
Записей в блоге: 2
05.10.2019, 16:35 8
Лучший ответ Сообщение было отмечено MollyLu как решение

Решение

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
.model medium
 
.stack 200h
 
.data
        CrLf            db      0Dh, 0Ah, '$'
        msgSource       db      'A source data: ', '$'
        msgResult       db      0Dh, 0Ah, 'Result: ', '$'
        msgPressAnyKey  db      0Dh, 0Ah, 'Press any key to exit...', '$'
        _STDOUT_        equ     1
        String          db      'MMXIX'
        _StrLen_        =       $-String
 
 
        ;                       A       B       C       D       E       F
        Roman           dw      0,      0,      100,    500,    0,      0
        ;                       G       H       I       J       K       L
                        dw      0,      0,      1,      0,      0,      50
        ;                       M       N       O       P       Q       R
                        dw      1000,   0,      0,      0,      0,      0
        ;                       S       T       U       V       W       X
                        dw      0,      0,      0,      5,      0,      10
        ;                       Y       Z
                        dw      0,      0
.data?
        Result          dw      ?
.code
 
;Вывод на экран целого 16 разрядного беззнакового числа
;на входе:
;  ax - целое 16 разрядное беззнаковое число
ShowUInt16       proc
        push    bx
        mov     bx,     10
        xor     cx,     cx      ;символов в модуле числа
        @@div:
                xor     dx,     dx
                div     bx
                push    dx
                inc     cx      ;количество цифр в числе
                or      ax,     ax
        jnz     @@div
        mov     ah,     02h
        @@store:
                pop     dx
                add     dl,     '0'
                int     21h
        loop    @@store
        pop     bx
        ret
ShowUInt16       endp
 
main    proc
        ;инициализация сегментного регистра ds адресом сегмента данных
        mov     ax,     @data
        mov     ds,     ax
 
        ;вывод исходных данных
        mov     ah,     09h
        lea     dx,     [msgSource]
        int     21h
        mov     ah,     40h
        mov     bx,     _STDOUT_
        mov     cx,     _StrLen_
        lea     dx,     [String]
        int     21h
 
        ;преобразование строки, содержащей запись римского числа, в число
        xor     di,     di              ;Temp := 0
        mov     cx,     _StrLen_        ;for i:=1 to length(String) do
        jcxz    @@break
        lea     si,     [String]
        @@for:                          ;begin
                xor     bx,     bx      ;  if not String[i] in ['I','V','X','L','C','D','M'] then
                mov     bl,     [si]    ;    break
                inc     si
                sub     bl,     'A'
                jc      @@break
                cmp     bl,     'Z'-'A'
                jnc     @@break
 
                add     bx,     bx      ;  term := Roman[String[i]]
                mov     ax,     Roman[bx]
                test    ax,     ax
                jz      @@break
 
                cmp     cx,     1       ; if i<length(String) then
                je      @@add           ;  begin
 
                mov     bl,     [si]    ;    if not String[i+1] in ['I','V','X','L','C','D','M'] then
                sub     bl,     'A'     ;      break
                jc      @@break
                cmp     bl,     'Z'-'A'
                jnc     @@break
 
                add     bx,     bx      ;  next := Roman[String[i+1]]
                mov     bx,     Roman[bx]
                test    bx,     bx
                jz      @@break
 
                xor     dx,     dx      ;    if term<next then
                cmp     ax,     bx      ;      term := -Roman[String[i]]
                sbb     dx,     dx      ;
                xor     ax,     dx      ;
                sub     ax,     dx
        @@add:                          ;  end
                add     di,     ax      ;  Temp := Temp+term
 
        loop    @@for                   ;end
        mov     [Result],       di      ;Result := Temp
        @@break:
 
        ;вывод результата
        mov     ah,     09h
        lea     dx,     [msgResult]
        int     21h
        mov     ax,     [Result]
        call    ShowUInt16
        ;ожидание нажатия любой клавиши
        mov     ah,     09h
        lea     dx,     [msgPressAnyKey]
        int     21h
 
        mov     ah,     00h
        int     16h
 
        ;завершение программы
        mov     ax,     4C00h
        int     21h
main    endp
 
end     main
1
0 / 0 / 0
Регистрация: 10.10.2016
Сообщений: 34
06.12.2019, 08:36  [ТС] 9
Всем спасибо за помощь! Прилагаю ниж свою реализацию полной программы. Не идеальна, знаю, но рабочая)

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
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
.model medium
 
.stack 200h
 
.data
        
CrLf                db      0Dh, 0Ah, '$'
Work                db      0Dh, 0Ah,'I am work!', '$'
msgSource           db      0Dh, 0Ah,'A source data: ', '$'
msgResult           db      0Dh, 0Ah, 'Result: ', '$'
msgResultAdd        db      0Dh, 0Ah, 'Result Add: ', '$'
msgResultSub        db      0Dh, 0Ah, 'Result Sub: ', '$'
msgResultMul        db      0Dh, 0Ah, 'Result Mul: ', '$'
msgPressAnyKey      db      0Dh, 0Ah, 'Press any key to exit...', '$'
msgError            db      0Dh, 0Ah, 'Input error... Press any key', '$'
_STDOUT_            equ      1
String_1            db       9 dup ('$') 
_StrLen1_           db       0
String_2            db       9 dup ('$')
_StrLen2_           db       0
del                 dw      10
 
        ;                       A       B       C       D       E       F
        Roman           dw      0,      0,      100,    500,    0,      0
        ;                       G       H       I       J       K       L
                        dw      0,      0,      1,      0,      0,      50
        ;                       M       N       O       P       Q       R
                        dw      1000,   0,      0,      0,      0,      0
        ;                       S       T       U       V       W       X
                        dw      0,      0,      0,      5,      0,      10
        ;                       Y       Z
                        dw      0,      0
.data? 
prov            db      ?
Result1         dw      ?
Result2         dw      ?
AddRes          dw      ?
SubRes          dw      ?
MulRes          dw      ?
MulResChas      dw      ?
MulResOst       dw      ?
        
.code
.386
;ввод чисел
 
    
;Вывод на экран целого 16 разрядного беззнакового числа
;на входе:
;  ax - целое 16 разрядное беззнаковое число
ShowUInt16       proc
        push    bx
        mov     bx,     10
        xor       cx,     cx      ;символов в модуле числа
        @@div:
                    xor     dx,     dx
                div         bx
                    push    dx
                    inc     cx      ;количество цифр в числе
                    or          ax,     ax
        jnz     @@div
        mov     ah,     02h
        @@store:
                pop      dx
                add      dl,     '0'
                int        21h
        loop    @@store
        pop     bx
        ret
ShowUInt16       endp 
 
main    proc
        ;инициализация сегментного регистра ds адресом сегмента данных
        mov     ax,     @data
        mov     ds,     ax
        xor     ax,     ax
        mov     cx,     9
        mov     si,     0
        ;вывод исходных данных первой строки
        
        mov     ah,     09h
        lea     dx,     [msgSource]
        int     21h
    
    goFirst:
        mov     ah,     01h                       ; Считывание первoго символа
        int     21h
          
        mov     prov,   al                      ; Перемещение введенного символа из al в bh 
                                                ; (al потом    затерается)
        CMP     prov,   0FFh
        je      goFirst
        
        CMP     prov,   0Dh
        je      brk_first 
        
        mov     bh,     prov
        mov     String_1[si],   bh
       
        inc     _StrLen1_ 
        inc     si 
        loop    goFirst
       
    brk_first:
        cmp     _StrLen1_,  0
        je      goFirst    
        jmp     rom1
    
    
    rom1:    
        ;преобразование строки, содержащей запись римского числа, в число
        xor     di,     di              ;Temp := 0
        mov     ch,     0
        mov     cl,     _StrLen1_       ;for i:=1 to length(String) do
        cmp     cx,     0 
        je    @@break
        lea     si,     [String_1]
        @@for1:                          ;begin
                xor     bx,     bx      ;  if not String[i] in ['I','V','X','L','C','D','M'] then
                mov     bl,     [si]    ;    break
                inc     si
                sub     bl,     'A'
                jc      @@break
                cmp     bl,     'Z'-'A'
                jnc     @@break
 
                add     bx,     bx      ;  term := Roman[String[i]]
                mov     ax,     Roman[bx]
                test    ax,     ax
                jz      @@break
 
                cmp     cx,     1       ; if i<length(String) then
                je      @@add1           ;  begin
 
                mov     bl,     [si]    ;    if not String[i+1] in ['I','V','X','L','C','D','M'] then
                sub     bl,     'A'     ;      break
                jc      @@break
                cmp     bl,     'Z'-'A'
                jnc     @@break
 
                add     bx,     bx      ;  next := Roman[String[i+1]]
                mov     bx,     Roman[bx]
                test    bx,     bx
                jz      @@break
 
                xor     dx,     dx      ;    if term<next then
                cmp     ax,     bx      ;      term := -Roman[String[i]]
                sbb     dx,     dx      ;
                xor     ax,     dx      ;
                sub     ax,     dx
        @@add1:                          ;  end
                add     di,     ax      ;  Temp := Temp+term
 
        loop    @@for1                   ;end
        mov     [Result1],       di      ;Result := Temp
        jmp     ToResult1
 
    ToResult1:  ;вывод результата
        mov     ah,     09h
        lea     dx,     [msgResult]
        int     21h
        mov     ax,     [Result1]
        call    ShowUInt16
        
;////////////////////////////////////////////////////////////// 
           
        mov cx, 9
        mov si, 0 
        
        mov     ah,     09h
        mov     dx,     offset msgSource
        int     21h
        
    goSecond: 
        mov     ah,     01h                        ; Считывание первoго символа
        int     21h
          
        mov     prov,   al                      ; Перемещение введенного символа из al в bh (al потом затерается) 
        
        CMP     prov,   0Dh
        je      brk_second
        
        CMP     prov,   0FFh 
        je      goSecond  
        
        mov     bh,     prov
        mov     String_2[si],   bh
        
        inc     _StrLen2_
        inc     si
        loop    goSecond 
 
    brk_second:
        cmp     _StrLen2_,  0
        je      goSecond       
        jmp     rom2
    
    rom2:   
        xor     di,     di              ;Temp := 0
        mov     ch,     0
        mov     cl,     _StrLen2_       ;for i:=1 to length(String) do
        jcxz    @@break
        lea     si,     [String_2]
        @@for2:                          ;begin
                xor     bx,     bx      ;  if not String[i] in ['I','V','X','L','C','D','M'] then
                mov     bl,     [si]    ;    break
                inc     si
                sub     bl,     'A'
                jc      @@break
                cmp     bl,     'Z'-'A'
                jnc     @@break
 
                add     bx,     bx      ;  term := Roman[String[i]]
                mov     ax,     Roman[bx]
                test    ax,     ax
                jz      @@break
 
                cmp     cx,     1       ; if i<length(String) then
                je      @@add2           ;  begin
 
                mov     bl,     [si]    ;    if not String[i+1] in ['I','V','X','L','C','D','M'] then
                sub     bl,     'A'     ;      break
                jc      @@break
                cmp     bl,     'Z'-'A'
                jnc     @@break
 
                add     bx,     bx      ;  next := Roman[String[i+1]]
                mov     bx,     Roman[bx]
                test    bx,     bx
                jz      @@break
 
                xor     dx,     dx      ;    if term<next then
                cmp     ax,     bx      ;      term := -Roman[String[i]]
                sbb     dx,     dx      ;
                xor     ax,     dx      ;
                sub     ax,     dx
        @@add2:                          ;  end
                add     di,     ax      ;  Temp := Temp+term
 
        loop    @@for2                   ;end
        mov     [Result2],       di      ;Result := Temp
        jmp     ToResult2
        @@break:
                mov     ah,     09h
                lea     dx,     [msgError]
                int     21h
        
 
                mov     ah,     00h
                int     16h
                
                mov     ax,     4C00h
                int     21h
    ToResult2:  
        ;вывод результата
        mov     ah,     09h
        lea     dx,     [msgResult]
        int     21h
        mov     ax,     [Result2]
        call    ShowUInt16
        
    
    AddResult:  ;делаем сумму двух строк
        xor     ax,     ax
        mov     ax,     Result1
        add     ax,     Result2
        mov     AddRes,     ax
        mov     ah,     09h
        lea     dx,     [msgResultAdd]
        int     21h
        mov     ax,     [AddRes]
        call    ShowUInt16
        
        
        mov     ax,     Result1
        mov     dx,     Result2
        sub     ax,     dx
        cmp     ax,     0
        jl      perevorot   
        jcxz    kak_est
            
            
        
        
            perevorot:
                
                xor     ax,     ax
                xor     dx,     dx
                mov     ax,     Result2
                mov     dx,     Result1
                sub     ax,     dx
                mov     SubRes, ax
                mov     ah,     09h
                lea     dx,     [msgResultSub]
                int     21h
                mov     ah,     02h
                mov     dl,     '-'             
                int     21h
                mov     ax,     [SubRes]
                call    ShowUInt16
                jmp     mult
            
        
            kak_est:
                
                mov     SubRes,     ax
                mov     ah,     09h
                lea     dx,     [msgResultSub]
                int     21h
                mov     ax,     [SubRes]
                call    ShowUInt16
        ;умножение
        mult:
            xor     ax,     ax
            xor     dx,     dx
            xor     bx,     bx
            mov     bx,     Result2
            mov     ax,     Result1
            imul    bx
            
            mov     ah,     09h
            lea     dx,     [Work]
            int     21h
            
            idiv    del
            
            
            mov     MulResChas,     ax
            mov     MulResOst,      dx
            
            mov     ah,     09h
            lea     dx,     [Work]
            int     21h
            
            
            xor     dx,     dx
            xor     ax,     ax
            mov     ah,     09h
            lea     dx,     [msgResultMul]
            int     21h
            
            cmp     dx,     0
            jne     vivod_ost
            jcxz    vivod_chas
            
            
            
            vivod_chas:
            mov     ah,     09h
            mov     ax,     [MulResChas]
            call    ShowUInt16
            
            vivod_ost:
            mov     ah,     09h
            mov     ax,     [MulResChas]
            call    ShowUInt16
            
            xor     ax,     ax
            mov     ax,     [MulResOst]
            call    ShowUInt16
        
        
        ;ожидание нажатия любой клавиши
        
        
        mov     ah,     09h
        lea     dx,     [msgPressAnyKey]
        int     21h
        
 
        mov     ah,     00h
        int     16h
        
        
        ;завершение программы
        mov     ax,     4C00h
        int     21h
main    endp
 
end     main
0
Модератор
Эксперт по электронике
7758 / 3908 / 1503
Регистрация: 01.02.2015
Сообщений: 12,061
Записей в блоге: 2
08.12.2019, 21:07 10
Лучший ответ Сообщение было отмечено MollyLu как решение

Решение

MollyLu, при выводе результатов умножения у вас ошибка - после умножения не сразу сохраняете результат, а сначала затираете его.
Ввод и преобразование строки можно вынести в процедуру - программа сократится почти в 3 раза.

Добавлено через 41 минуту
Так программа сокращается до
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
.model medium
 
.stack 200h
 
.data
        CrLf            db      0Dh, 0Ah, '$'
        msgFirst        db      'Enter a first number (in roman): ', '$'
        msgSecond       db      0Dh, 0Ah, 'Enter a second number (in roman): ', '$'
        msgEntered      db      0Dh, 0Ah, 'Entered: ', '$'
        msgResult       db      0Dh, 0Ah, 'Result: ', '$'
        msgPressAnyKey  db      0Dh, 0Ah, 'Press any key to exit...', '$'
        msgAdd          db      0Dh, 0Ah, 'Add: ', '$'
        msgSub          db      0Dh, 0Ah, 'Sub: ', '$'
        msgMul          db      0Dh, 0Ah, 'Mul: ', '$'
        msgDiv          db      0Dh, 0Ah, 'Div: ', '$'
 
        ;                       A       B       C       D       E       F
        Roman           dw      0,      0,      100,    500,    0,      0
        ;                       G       H       I       J       K       L
                        dw      0,      0,      1,      0,      0,      50
        ;                       M       N       O       P       Q       R
                        dw      1000,   0,      0,      0,      0,      0
        ;                       S       T       U       V       W       X
                        dw      0,      0,      0,      5,      0,      10
        ;                       Y       Z
                        dw      0,      0
.data?
        First           dw      ?
        Second          dw      ?
        Result          dw      ?
        kbdBuffer       db      12 dup(?)
.code
 
; выводит знаковое 16-разрядное число из регистра AX на экран
; на входе:
;  ax - число для отображения
; на выходе:
;  число на экране
ShowInt16       proc
        push    ax
        push    bx
        push    cx
        push    dx
        mov     bx,     10      ;основание системы счисления (делитель)
        xor     cx,     cx      ;количество символов в модуле числа
        or      ax,     ax      ;для отрицательного числа
        jns     @@div
                neg     ax      ;поменять знак (сделать положительным)
                push    ax      ;и вывести на экран символ "-" (минус)
                mov     ah,     02h
                mov     dl,     '-'
                int     21h
                pop     ax
        @@div:                  ;делим число на 10
                xor     dx,     dx
                div     bx
                push    dx      ;остаток сохраняем в стеке
                inc     cx      ;количество цифр в числе
                or      ax,     ax
        jnz     @@div           ;повторяем, пока в числе есть цифры
        mov     ah,     02h
        @@store:
                pop     dx      ;извлекаем цифры (остатки от деления на 10) из стека
                add     dl,     '0'     ;преобразуем в символы цифр
                int     21h     ;и выводим их на экран
        loop    @@store
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
ShowInt16       endp
 
;преобразование строки, содержащей запись римского числа, в число
;на входе:
;  ds:si - строка для преобразования
;  cx    - длина строки
;на выходе:
;  ax - число
RomanToInt      proc
        push    bx
        push    cx
        push    dx
        push    si
        push    di
 
        xor     di,     di              ;Temp := 0
        ;mov     cx,     _StrLen_       ;for i:=1 to length(String) do
        jcxz    @@break
        ;lea     si,     [String]
        @@for:                          ;begin
                xor     bx,     bx      ;  if not String[i] in ['I','V','X','L','C','D','M'] then
                mov     bl,     [si]    ;    break
                inc     si
                sub     bl,     'A'
                jc      @@break
                cmp     bl,     'Z'-'A'
                jnc     @@break
 
                add     bx,     bx      ;  term := Roman[String[i]]
                mov     ax,     Roman[bx]
                test    ax,     ax
                jz      @@break
 
                cmp     cx,     1       ; if i<length(String) then
                je      @@add           ;  begin
 
                mov     bl,     [si]    ;    if not String[i+1] in ['I','V','X','L','C','D','M'] then
                sub     bl,     'A'     ;      break
                jc      @@break
                cmp     bl,     'Z'-'A'
                jnc     @@break
 
                add     bx,     bx      ;  next := Roman[String[i+1]]
                mov     bx,     Roman[bx]
                test    bx,     bx
                jz      @@break
 
                xor     dx,     dx      ;    if term<next then
                cmp     ax,     bx      ;      term := -Roman[String[i]]
                sbb     dx,     dx      ;
                xor     ax,     dx      ;
                sub     ax,     dx
        @@add:                          ;  end
                add     di,     ax      ;  Temp := Temp+term
 
        loop    @@for                   ;end
        mov     ax,     di              ;Result := Temp
        @@break:
        pop     di
        pop     si
        pop     dx
        pop     cx
        pop     bx
        ret
RomanToInt      endp
 
;ввод числа
;на входе:
;  ds:dx - указатель на строку предложения ввода
;  ds:di - указатель на вводимую переменную
Input   proc
        mov     ah,     09h
        int     21h
        mov     [kbdBuffer],    word ptr 10
        mov     ah,     0Ah
        lea     dx,     [kbdBuffer]
        int     21h
        mov     ch,     0
        mov     cl,     [kbdBuffer+1]
        lea     si,     [kbdBuffer+2]
        call    RomanToInt
        mov     [di],   ax
        mov     ah,     09h
        lea     dx,     [msgEntered]
        int     21h
        mov     ax,     [di]
        call    ShowInt16
        ret
Input   endp
 
main    proc
        ;инициализация сегментного регистра ds адресом сегмента данных
        mov     ax,     @data
        mov     ds,     ax
 
        ;ввод исходных данных
        ; - первый опреанд
        lea     dx,     [msgFirst]
        lea     di,     [First]
        call    Input
        ; - второй опреанд
        lea     dx,     [msgSecond]
        lea     di,     [Second]
        call    Input
        ;вывод результатов
        ; - сложения
        mov     ah,     09h
        lea     dx,     [msgAdd]
        int     21h
        mov     ax,     [First]
        add     ax,     [Second]
        call    ShowInt16
        ; - вычитания
        mov     ah,     09h
        lea     dx,     [msgSub]
        int     21h
        mov     ax,     [First]
        sub     ax,     [Second]
        call    ShowInt16
        ; - умножения
        mov     ah,     09h
        lea     dx,     [msgMul]
        int     21h
        mov     ax,     [First]
        mul     [Second]
        call    ShowInt16
        ; - деления
        mov     ah,     09h
        lea     dx,     [msgDiv]
        int     21h
        mov     ax,     [First]
        xor     dx,     dx
        div     [Second]
        call    ShowInt16
 
        ;ожидание нажатия любой клавиши
        mov     ah,     09h
        lea     dx,     [msgPressAnyKey]
        int     21h
 
        mov     ah,     00h
        int     16h
 
        ;завершение программы
        mov     ax,     4C00h
        int     21h
main    endp
 
end     main
Согласитесь, что сложнее сделать ошибку при многократном вызове отлаженной подпрограммы, чем при копировании её содержимого.
Да и сама структура программы становится "прозрачнее".

Можно улучшить программу, вводя строку по одному символу и фильтруя ввод. Но придётся делать и обработку функциональных клавиш. Хотя в учебных целях можно обойтись только фильтрацией допустимых символов.
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.12.2019, 21:07

Арабские цифры в римские
Помогите пожалуйста в решении задачи: Для представления римских цифр используются символы: I -...

Арабские цифры в римские
Возможно кто-то сталкивался и может поделиться? 1-&gt; I 2-&gt; II 3-&gt;III 4-&gt;IV ну, и так далее. ...

Арабские цифры в римские
Перевод арабских цифр в римские. Саму задачу я решил, так что код как таковой мне не нужен, просто...

Арабские цифры в римские
Для записи римскими цифрами используются символы I, V, X, L, С, D, М, обозначающие соответственно...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru