Форум программистов, компьютерный форум, киберфорум
Assembler, MASM, TASM
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
0 / 0 / 0
Регистрация: 18.12.2010
Сообщений: 22

Исправление ошибки

08.05.2012, 15:33. Показов 1579. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Нужна помощь!!! Наткнулась в нете на код, который подходит к моей задаче. Стала его проверять, а он немного не работает, похоже какая-то ошибка при выводе. Никак не могу найти где она(((

Задание следующее: Разбить входные числа на массив положительных и массив отpицательных чисел, вычислить попаpные пpоизведения и их сумму.
При этом проводится проверка на ввод.

Помогите плиз! ОЧень надо. У меня win7, использую MASM. Заранее спасибо)
Вот код:
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
;Разбить входные числа на массив положительных и массив отpицательных чисел, вычислить попаpные пpоизведения и их сумму.
 
COUNT    equ    16 ;EQU - одна из команд препроцессора. EQU присваивает ячейке символическое имя и позволяет работать в тексте программы с именем переменной
;объявляем переменную 'count'
 
d1    segment para public 'data'
mess1        db 'Enter numbers (For the input termination, press twice key "Enter"):',10,13,'$'
mess2        db 10,13,'Output array:',10,13,'$'
messNoPos    db 10,13,'Positive numbers are not entered! Please, repeat input',10,13,'$'
messNoNeg    db 10,13,'Negative numbers are not entered! Please, repeat input',10,13,'$'
messOper    db 10,13,'1. Calculate sum'    ;меню
        db 10,13,'2. Calculate mul'
        db 10,13,'3. Exit'
        db 10,13,'Your choice: $'
in_str        db 22 dup (?)        ;строка для ввода числа
pos_cnt        dw ?                ;количество положительных
neg_cnt        dw ?                ;количество отрицательных
positive    dw COUNT dup (?)    ;массив положительных (max COUNT)
negative    dw COUNT dup (?)    ;массив отрицательных (max COUNT)
d1 ends
 
st1    segment para stack 'stack'
    dw 100 dup (?)
st1    ends
 
c1    segment para public 'code'
assume    cs:c1,ds:d1,ss:st1
start:    mov    ax,d1
        mov    ds,ax
        mov    in_str,20        ;подготовим буфер ввода числа
povtor:
    mov    pos_cnt,0        ;обнулим счетчики
    mov    neg_cnt,0
        mov    dx,offset mess1    ;Приглашение ввода
        mov    ah,9            ;функция прерывания 21h DOS для вывода на экран строки символов
        int    21h    
    mov    cx,COUNT        ;вводим максимум COUNT чисел
input:
        mov    dx,offset in_str
        mov    ah,0ah            ;функция прерывания 21h DOS для ввода с клавиатуры строки символов
        int    21h
        cmp    in_str+1,0        ;по пустой строке заканчиваем ввод
    jz    comp_counts        ;проверим счетчики
 
    call    GetNum            ;преобразуем строку в число (в AX)
    jc    povtor            ;при ошибке на повтор ввода
 
    test    ax,ax            ;проверим знак числа
    js    save_negative
save_positive:
    mov    di,pos_cnt        ;счетчик положительных одновременно является индексом места, куда пишем
    shl    di,1            ;только умножим его на 2, чтобы адресовать слово
    mov    positive[di],ax        ;сохраняем
    inc    pos_cnt            ;инкремент количества положительных
    jmp    next_row        ;на перевод строки
save_negative:
    mov    di,neg_cnt        ;то же самое для отрицательных
    shl    di,1
    mov    negative[di],ax
    inc    neg_cnt
next_row:
    mov    al,0ah            ;перевод строки
    int    29h ;функция DOS вывода на экран — недокументированное прерывание 29h. Быстрый вывод символа на экран. В большинстве случаев INT 29h просто немедленно вызывает функцию BIOS «вывод символа на экран в режиме телетайпа», так что никаких преимуществ, кроме экономии байт при написании как можно более коротких программ, она не имеет.
    loop    input            ;повторим ввод чисел
 
comp_counts:
    cmp    pos_cnt,0        ;были ли введены положительные числа
    jne    comp_neg
    lea    dx,messNoPos        ;сообщение об ошибке (не были введены положительные числа)
    jmp    Message
comp_neg:
    cmp    neg_cnt,0        ;были ли введены отрицательные числа
    jne    output
    lea    dx,messNoNeg        ;сообщение об ошибке (не были введены отрицательные числа)
Message:
    mov    ah,9
    int    21h
    jmp    povtor            ;на повтор ввода
 
output:                    ;выведем введенные числа
    mov    dx,offset mess2 ;Вывод
        mov    ah,9 ; функция прерывания 21h DOS для вывода на экран строки символов
        int    21h
 
    mov    cx,pos_cnt        ;число положительных
    lea    si,positive        ;их адрес
    call    PrintNumbers
 
    mov    cx,neg_cnt        ;отрицательные
    lea    si,negative
    call    PrintNumbers
 
oper_loop:                ;вывем меню и отработаем операции
    mov    dx,offset messOper    ;Вывод
        mov    ah,9            ; функция прерывания 21h DOS для вывода на экран строки символов
        int    21h
 
    mov    ah,1            ;ввод кода клавиши с одновременным выводом на экран
        int    21h
 
    push    ax
    mov    al,0ah            ;перевод строки
    int    29h
    pop    ax
                    ;проанализируем код (в al)
    cmp    al,'3'            ;если 3, то выход
    je    exit
    cmp    al,'1'            ;если 1, то сумма
    je    summa
    cmp    al,'2'            ;если 2, то произведение
    jne    oper_loop        ;если что-то другое, то на повтор
    xor    bp,bp            ;признак произведения
    jmp    calc_oper
summa:
    mov    bp,1            ;признак суммы
calc_oper:
    mov    cx,pos_cnt        ;количество положительных
    mov    bx,neg_cnt        ;кол отрицательных
    lea    si,positive        ;адрес положительных
    lea    di,negative        ;адрес отрицательных
    cmp    cx,bx            ;найдем минимум
    jbe    next_oper
    xchg    cx,bx
    xchg    si,di
next_oper:                ;сначала отработаем общую часть
                    ;в CX минимум из наборов, в SI - его адрес!
    lodsw                ;загрузка (слова) в AX первого операнда
    test    bp,bp            ;код операции
    jz    mult
    add    ax,[di]
    jmp    print_oper
mult:
    imul    word ptr [di]        ;знаковое умножение
print_oper:
    add    di,2            ;сдвинем индекс второго операнда
    call    PrintNum        ;выведем
    cmp    bx,1            ;в случае одинаковых количеств обойдем вывод запятой
    je    print_last
    mov    al,','            ;разделительные запятая и пробел
    int    29h
    mov    al,' '
    int    29h
    dec    bx            ;уменьшим счетчик большего набора
    loop    next_oper
                    ;выведем остаток болшьшего набора
    mov    cx,bx            ;оставшееся количество в большем наборе
print_tail:
    mov    ax,[di]            ;значение
    add    di,2            ;сдвинем индекс
    call    PrintNum        ;выведем
    cmp    cx,1            ;обойдем вывод запятой после последнего числа
    je    Print_last
    mov    al,','            ;разделительные запятая и пробел
    int    29h
    mov    al,' '
    int    29h
    loop    print_tail
 
Print_last:                ;перевод строки
    mov    al,0dh
    int    29h
    mov    al,0ah
    int    29h
    jmp    oper_loop        ;перейти на вывод меню
exit:
        mov    ax,4c00h        ;выход
        int    21h
;
PrintNumbers    proc            ;вывод введенных чисел
PN_loop:
    lodsw                ;число
    call    PrintNum        ;вывод
    cmp    cx,1            ;обойдем вывод запятой после последнего числа
    je    PN_last
    mov    al,','
    int    29h
    mov    al,' '
    int    29h
    loop    PN_loop
PN_last:
    mov    al,0dh            ;перевод строки
    int    29h
    mov    al,0ah
    int    29h
    ret
PrintNumbers    endp
 
PrintNum    proc        ; вывод числа из AX
    push    bx 
    test    ax, ax        ;проверим на знак
    jns    form_str    ;для положительного на вывод
    push    ax        ;для отрицательного выводим - и меняем знак
    mov    al,'-'        ;знак -
    int    29h
    pop    ax
    neg    ax        ;меняем знак числа на +, теперь оно положительное
 
form_str:
    mov    bx, 10        ; будем делить на 10
    xor    cx, cx        ; счетчик цифр
div_loop:            ; цикл получения десятичных разрядов
    xor    dx, dx        ; подготовимся для очередного деления
    div    bx        ; в dx остаток - очередной десятичный разряд
    push    dx        ; сохраним в стеке (от младшего к старшему)
    inc    cx        ; посчитаем
    test    ax, ax        ; есть еще десятичные разряды?
    jnz    div_loop    ; продолжим
 
pr_loop:            ; цикл вывода десятичных цифр-символов
    pop    ax        ; востановим очередной разряд (от старшего к младшему)
    add    al, '0'        ;  символ цифры
    int    29h        ; вывод
    loop    pr_loop        ; по всем цифрам
    pop    cx 
    ret
PrintNum    endp
;
GetNum    proc            ; преобразование сроки в число
    push    cx
    xor    di, di        ; здесь будем накапливать число
    mov    cl, 0        ; флаг знака
    mov    ch, 0        ; количество цифр
    xor    bx, bx        ; очередной знак (для сложения со словом)
        mov    si,offset in_str+2 ;первый символ для обработки 
get_num_loop:
    lodsb            ; очередная цифра
; проверим на разделители
    cmp    al, 0dh
    je    num_end_found    ; конец ввода
    cmp    al, ' '
    je    num_end_found
    cmp    al, 9
    je    num_end_found
; минус может быть только один и в первой позиции!    
    cmp    al, '-'
    jne    cmp_num
    test    ch, ch        ; были ли введены цифры?
    jnz    set_c        ; были - ошибка - минус не в первой позиции!
    test    cl, cl        ; был ли уже введен минус?
    jnz    set_c        ; был - ошибка - можно только один!
    mov    cl, 1        ; пометим отрицательное число
    jmp    get_num_loop    ; на анализ следующего символа
cmp_num:
    cmp    al, '0'        ; цифра?
    jb    set_c        ; ошибка - не цифра!
    cmp    al, '9'
    ja    set_c
 
    inc    ch        ; считаем цифры
    and    al, 0fh        ; цифра -> число (30h-39h -> 0-9)
    mov    bl, al        ; сохраним (bh=0)
    mov    ax, 10        ; умножим на 10 
    imul    di        ; предыдущее значение
    test    dx, dx        ; больше cлова - ошибка!
    jnz    set_c
    add    ax, bx        ; добавим сохраненный разряд
    jc    set_c        ; больше  слова - ошибка!
    js    set_c        ; больше 32767 - ошибка!
    mov    di, ax        ; сохраним
    jmp    get_num_loop    ; идём на анализ следующего символа
 
num_end_found:            ; встретили разделитель
    test    ch, ch        ; что-то было?
    jz    set_c        ; не было числа (например, был введен один минус)
    test    cl, cl        ; число отрицательное?
    jz    get_num_ret
    neg    di        ; дополнительный код отрицательного числа
get_num_ret:
    mov    ax, di        ; результат в ax
    pop    cx
    clc            ; все ок. Команда clc сбрасывает флаг переноса CF в регистре флагов. Команда не имеет параметров и не воздействует на остальные флаги процессора.
    ret ; Возврат из процедуры, вызванной командой call
set_c:
    pop    cx
    stc            ; ошибка. Установка флага переноса CF в 1
    ret
GetNum    endp    
 
c1    ends
 
    end    start
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.05.2012, 15:33
Ответы с готовыми решениями:

Исправление ошибки в программе
Всем здрасьте! Помогите пожалуйста с ошибкой. Программа должна работать, по идее, но она увы вредничает. Компилирую в ТАСМ5. Ошибки: ...

Исправление ошибки в коде
Помогите исправить ошибку в коде... от этого зависит моя сессия ATMEGA16 Задание и схему устройства прикреплю

Исправление ошибки на DEBUG
Предположим, введена такая команда DEBUG: Е CS:100 B8 45 01 05 25 00 Значение 45 на самом деле должно было быть 54. какую надо ввести...

4
116 / 136 / 0
Регистрация: 15.04.2012
Сообщений: 1,031
09.05.2012, 06:17
Цитата Сообщение от Konfetkadetka Посмотреть сообщение
Assembler
1
2
cmp al, 9
 je num_end_found
Странно это что-то, что за 9 символ. Может кто-нибудь знает?
0
 Аватар для _lucius_
391 / 179 / 2
Регистрация: 14.03.2012
Сообщений: 443
09.05.2012, 10:33
Цитата Сообщение от programmisto Посмотреть сообщение
Странно это что-то, что за 9 символ. Может кто-нибудь знает?
Табуляция.

Добавлено через 1 час 14 минут
Konfetkadetka, ошибка из-за того, что в цикле созданном командой loop (уменьшают cx на один, после чего выполняют переход если cx не равен нулю) используется функция PrintNum которая не сохраняет состояние регистра cx. Из-за этого цикл бесконечный. Т.е. в трёх местах программы, заменить:
Assembler
1
call PrintNum
на:
Assembler
1
2
3
    push cx
    call PrintNum 
    pop cx
И следует учитывать, что числа вводятся по одному, ввели (знак) число жмем интер, ввели (знак) число жмем интер и т.д. Пока не введем 16 чисел.
1
0 / 0 / 0
Регистрация: 18.12.2010
Сообщений: 22
09.05.2012, 12:22  [ТС]
Ураааа! Все работает) Огромное спасибо!
0
 Аватар для _lucius_
391 / 179 / 2
Регистрация: 14.03.2012
Сообщений: 443
09.05.2012, 12:26
Пожалуйста.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
09.05.2012, 12:26
Помогаю со студенческими работами здесь

Исправление ошибки в программе вычисления CRC16
Добрый день! Возникла проблема с кодом, код реализует окно с кнопкой для выбора файла,из файла берутся данные, данные прогоняются по...

Вычисление полинома по схеме Горнера (исправление ошибки)
Помогите исправить ошибку. При отрицательном x программа считает неправильно. При заданных параметрах ассемблер выдает 995917 ...

Исправление ошибки при решении примера (linux nasm)
Привет, Всем) Не могли бы, Вы исправить ошибку в коде nasm (linux) Пример : ((a1+a2)*a3/a4+a5) a1=-7, a2=3, a3=2, a4=4, a5=2 mov...

Исправление вывода строки
Уважаемы форумчане, помогите поправить программу. Суть программы, вводим строку ограниченно длинны, например 5 символов, и выводим эту...

Исправление ошибок программы и ее дополнение
Вообщем, дал нам препод исправить ошибки программы написанной на ассемблере, 1-й шаг) ассемблировать код через через tasm.exe, 2-й...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит: токи, напряжения и их 1 и 2 производные при t = 0;. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru