Вопрос № 148505: Здравствуйте уважаемые эксперты! Пожалуйста проверте на ошибки и правильность написания программы, если неправильно - исправьте. Программирую недавно и вполне возможно, что все это абсолютно неправильно. Очень важно!!!!!!...
Вопрос № 148615: Здравствуйте, у меня два вопроса. 1) В первом приложении у меня написана программа «lohotron», она не много не доделана – еще скорость и ускорение нужно подобрать получше. Я столкнулся
вот с чем. В процедуре int_08h proc, которая...
Вопрос № 148.505
Здравствуйте уважаемые эксперты! Пожалуйста проверте на ошибки и правильность написания программы, если неправильно - исправьте. Программирую недавно и вполне возможно, что все это абсолютно неправильно. Очень важно!!!!!!
Отвечает: Зенченко Константин Николаевич
Здравствуйте, Коняхина Наталья!
Программа в приложении. Для ввода строк использована одна подпрограмма loadStr. Вся вводимая информация последовательно копируется в буфер вывода, а также дополняется до нужного размера пробелами, организованно с помощью строковых команд. Введенный параметр стоимость товара преобразовывается со строки в 16-тибитное число, с помощью подпрограммы str2num. Ещё добавлена одна ошибка :NumberMes db 13,10,'Ошибка неверное число$'. Если
будет введена пустая строка, то ввод параметра повторяется. Использовал малую модель организации памяти(сегмент кода + сегмент данных и стека), средняя модель организации памяти(несколько сегментов кода + сегмент данных) нерациональна для такой программы(всего 921 байт).
ps:вопросы по программе задавайте в мини-форум. Удачи!
Приложение:
--------- Итерация от человека, рекурсия — от Бога (Питер Дойч)
Ответ отправил: Зенченко Константин Николаевич (статус: Профессор) Украина, Киев Тел.: +380979536619 Адрес: Украина г.Киев ---- Ответ отправлен: 29.10.2008, 20:03
Как сказать этому эксперту "спасибо"?
Отправить SMS
#thank 148505 на номер 1151 (Россия) | Еще номера >>
Вам помогли? Пожалуйста, поблагодарите эксперта за это!
Оценка за ответ: 5
Вопрос № 148.615
Здравствуйте, у меня два вопроса.
1) В первом приложении у меня написана программа «lohotron», она не много не доделана – еще скорость и ускорение нужно подобрать получше. Я столкнулся вот с чем. В процедуре int_08h proc, которая вызывается таймером, пришлось обращения к переменным организовывать через сегментный регистр CS. Если такой префикс не добавлять, то по умолчанию используется DS. А вот DS как раз воспользоваться не получилось, так как он, почему-то изменяется. Вот это и оказалось
для меня новостью. До сих пор я считал, что при входе в прерывание в стек закидывается регистр флагов и дальний адрес возврата – и больше ничего не происходит. А вот оказывается не так: может я что не так понял? То что в коде взято в {{{…}}} – этого для работы программы не нужно – это эксперимент, чтобы увидеть регистры в этой процедуре. На каждых машинах конечно по разному, но например, «лог-файл» выглядит так: 48 0E 40 00 00 B8 48 0E. Как видите DS=0040H, хотя я
сам его не трогаю, а CS=0E48H.
mov ax,3 int 10h ;устанавливаем текстовый режим mov ah,9 mov dx,offset List int 21h ;выводим список, в данном случае, людей
mov ah,2 mov bh,0 mov dx,1900h int 10h ;убираем курсор за пределы экрана
mov ax,3508h int 21h mov word ptr old_08h,bx mov word ptr old_08h+2,es mov ax,2508h ;подменяем int 08h mov dx,offset int_08h ;{правильно потом назад возвращать - int 21h ;но запускаю из-под WINDOWS
(так называемый NTVDM), поэтому считаю не зачем} mov ax,0b800h mov es, ax ;строки будем закрашивать напрямую в видеобуфер ;==================================== ;далее придумка следующая: ;давим любую клавишу (кроме Esc) происходит разгон лохотрона - переменная jobTime уменьшается до нуля, ;отпустили клавишу - переменная jobTime увеличивается до 150 - полный останов. ;все изменения этой переменной в таймере. RIS: ;с этой метки основной цикл mov ah, 0 mov al, jobTime mov bx, 10 div bl inc al mov ah,0 mov di, ax ;di = jobTime div 10 + 1 число для задержки (ниже)
int 1ah mov bx,dx
;---------------------------- PAUSE: mov ah,1 int 16h jz PAUSE2 mov ah,0 ;если символ готов - извлекаем из очереди, int 16h cmp al, 1bh jz exit ;(Esc - выход)
mov KLV,1 ;и пометка для таймера - что клавиша нажата PAUSE2: mov ah,0 int 1ah sub dx,bx
cmp dx,
di ;задержка - пока dx - bx < di jc PAUSE ;---------------------------- mov al, 07h call blood ;убираем цветную строку на предыдущем месте
add place, 160 ;получаем адрес следующей строки, .if place == 160*CountList mov place, 0 ;с учетом закольцовки по количеству строк в списке .endif
.if jobTime > 10 ;это место для красоты - чтобы видеть, когда достигли полного разгона, mov al, 17h ;т.е. пока job
Time от 150 до 10 - цвет синий, .else ;если скорость разогналась от 10 до 0 - цвет зеленый. mov al, 27h .endif call blood
cmp jobTime, 150 ;когда jobTime достигла 150 - выполняется останов, jc RIS ; т.е. зацикливание прекращается. ;====================================
mov ah,0 int 16h ; есть возможность повторить разгон любой клавишей, кроме Esc cmp al, 1bh jnz RIS ;==================================== exit: mov ax,3 ;если
убрать эти строки: появлялась ошибка - int 10h ;"Системная ошибка NTVDM Параметр задан неверно" ;причем это связано с установкой курсора за пределы экрана - если там этого не делать, то и здесь не надо.
;{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ mov ah,3ch mov dx,offset file xor cx,cx int 21h
mov ah,3eh int 21h ;}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} .exit 0 ;{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ file db '1.txt',0 buf dw 4 dup (?) ;}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
blood proc ;заливка текущей строки шириной в 21 знакоместо mov di, place inc di mov cx, 21 BLACK: mov es:[di], al add di,2 loop BLACK ret blood endp
int_08h proc ;{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ mov cs:buf,
cs mov cs:buf+2, ds mov cs:buf+4, es mov cs:buf+6, ss ;}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
; push ds ; push cs ; pop ds .if cs:KLV ; если клавиша нажата: mov cs:KLV,0 ;то, во-первых, скидываем признак нажатия, .if cs:jobTime>=2 ;во-вторых, если разгон еще можно делать, то делаем dec cs:jobTime ; dec cs:jobTime .endif .elseif cs:jobTime<150 ;когд
а клавиша не нажата и еще не подошел момент останова, то уменьшаем "скорость" inc cs:jobTime .endif
; pop ds
jmp dword ptr cs:[old_08h] int_08h endp ; #################### END
2) Можно ли пользоваться нулевым прерыванием для обработки «переполнение при делении на ноль». Опять же чтобы не приняли меня за лодыря – я уже помучался (приложение 2). Примитивная мысль, которая меня посетила это скидывать бит переполнения в регистре флагов
(настоящий обработчик я вызывать как раз не хочу, потому что он выбрасывает программу в DOS). Этот бит скидываю в своем обработчике нулевого прерывания. Там конечно может что лишнее, проще сказать черновик. Содержимое стека скидываю в «лог-файл». В файле следующее: 02 30 19 01 47 0E 02 32 11 01 47 0E 02 32. 02 30 – содержимое флага в обработчике до того, как я его изменяю 19 01 47 0E 02 32 – адрес возврата и флаг до того, как я его изменяю 11 01 47 0E
02 32 – адрес возврата и флаг после того, как я его изменил.
Что здесь можно увидеть: Во-первых, 02 30 ни какого переполнения не вижу, а вот прерывания запрещены. Хотя если я не буду этот бит скидывать, то, однако работать не будет. Во флагах до захода в обработчик прерывания конечно разрешены : 02 32. А вот теперь с адресами возврата: 119h указывает на команду div bl, что собственно в литературе и говорится, т.е. на само деление. А вот когда я руки приложил к флагу, то 111h
– совершенно левый адрес. Перед делением есть закомментированная команда stc – с ней все сразу же висит. Но если и без нее просто визуально вреда не видно, а так в памяти все портится как я понял (по крайней мере как я видел с адреса cs:0).
Код:
CCC SEGMENT ORG 100H BEGIN: ; ############################## comment % mov si,sp mov di,offset buf mov cx,6 rep movsb ; call vyvyod % ; скопировать адрес предыдущего обработчика в переменную old_handler mov ax,3500h ; АН = 35h, AL = номер прерывания int 21h ; функция DOS: считать ; адрес обработчика прерывания
mov word ptr old_handler,bx ; возвратить ; смещение в ВХ mov word ptr old_handler+2,es ; и сегментный ; адрес в ES,
; обработчик ; (не забывайте, что ES изменился после вызова функции 35h!)
; установить наш обработчик mov ax,2500h ; АН = 25h,
AL = номер прерывания
mov dx,offset int_handler ; смещение в DX int 21h ; функция DOS: установить ;push cs ;pop es
Отвечает: Airyashov
Здравствуйте, Бартосик Феликс Михайлович! 1. т.к. прерывание может вызыватся из любой программы, у всех свой DS, то кто вам должен гарантировать какое-то значение в DS, если хотите использовать инициализируйте при в ходе в прерывание, только старое значение не портите.
Ответ отправил: Airyashov (статус: 10-ый класс)
Ответ отправлен: 27.10.2008, 12:12
Как сказать этому эксперту "спасибо"?
Отправить SMS
#thank 148615 на номер 1151 (Россия) | Еще номера >>
Вам помогли? Пожалуйста, поблагодарите эксперта за это!
Оценка за ответ: 3 Комментарий оценки: Собственно говоря, я и сам заметил что DS изменился и его нужно инициализировать. Я предполагал узнать - что в нем за число и зачем. Кстати, ES и SS тоже в каждой программе свои, но они не изменились.
Ну а про второй мой вопрос ни слова.
Скажите "спасибо" эксперту, который помог Вам!
Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
на короткий номер 1151 (Россия)
Номер ответа и конкретный текст СМС указан внизу каждого ответа.
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.