KBAC
|
|
« : 12-06-2012 14:45 » |
|
Здравствуйте всем. Надо заменить обработчик прерывания irq1. У меня получается его подменить, но выполняется он почему-то только один раз. А на дальнейшие дествия не реагирует. ;===================== ; my interrupt handler ;===================== my_handler_int9 proc pushf call ClearScreen xor ax,ax in al,60h and al,07Fh call ByteToHex lea dx,buffer call PrintStr_bios cmp al,01h je progover ; mov al,20h ; out 20h,al jmp cs:old_handler my_handler_int9 endp main proc assume cs:_text lds dx,dword ptr old_handler call int9_change ; exchange old_handler to my_handler xor bx,bx endless_loop: cmp bx,0Ah jne endless_loop call progover main endp ;================================ ; change interrupt handler ;================================ int9_change proc push ax push bx push dx push ds push es ; get old_handler mov ax,3509h ; ah = 35, al = 9 (irq1) int 21h ; get old_handler offset in es:bx ; remember old_handler's offset mov word ptr old_handler,bx mov word ptr old_handler+2,es ;write my_handler offset to vector's table ; new offset in ds:dx mov ax,2509h mov dx,seg my_handler_int9 mov ds,dx lea dx,my_handler_int9 pushf cli ; stop interrupting int 21h popf ; continue interrupting pop es pop ds pop dx pop bx pop ax ret int9_change endp Процедуры ByteToHex и др. отлажены.
|
|
|
Записан
|
У тебя все получится, главное -- верить и делать. Порадоваться, когда все плохо -- легче, чем ты думаешь. В действии счастье. Вовлекая людей важно быть увлеченным чужой жизнью.
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #1 : 12-06-2012 18:19 » |
|
KBAC, почему твой обработчик не сохраняет все регистры? Команды PUSHA и POPA.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #2 : 12-06-2012 18:46 » |
|
Из одного прерывания вызывать другое прерывание не рекомендуется. Насколько я понял ClearScreen и PrintStr_bios должны по идее говоря использовать. Насколько я помню, при вызове прерывания, флаг прерывания блокируется и во время выполнения прерывания, другие прерывания не вызываются. Разблакировка происходит при вызове iret.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #3 : 12-06-2012 20:42 » |
|
Finch, "программные прерывания" не маскируют аппаратные прерывания. Но по сути поддерживаю: мы ничего не знаем о вызываемых процедурах.
Каскадирование обработчиков через long jmp допускается.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #4 : 13-06-2012 05:30 » |
|
KBAC, кроме того, что сказали Finch и RXL, ещё в my_handler_int9 Вы вызываете jmp cs:old_handler, т.е. указатель old_handler у Вас в сегменте кода, а в int9_change - Вы сохраняете mov word ptr old_handler,bx - т.е. идёт неявная адресация по сегменту данных, проверьте, действительно они у Вас совпадают? Для избежания возможных проблем в будущем, тут лучше тоже. имхо, явно указывать, что ячейки находятся в cs. Кстати в данном случае word ptr, имхо, лишний - ассемблер по регистру bx сам может узнать, размерность приёмника.
|
|
« Последнее редактирование: 13-06-2012 08:14 от darkelf »
|
Записан
|
|
|
|
KBAC
|
|
« Ответ #5 : 13-06-2012 12:30 » |
|
RXL, пишу с использованием команд только 8086. Я вообще сомневаюсь в использовании pushf в моем обработчике. Ведь команды pushf call int_handler заменяет использование команды int. Наверно эта команда все же выполняется при вызове аппаратного прерывания. Т.е. если взять обработчик полностью заменяющий старый обработчик я должен в конце (из обязательного) поставить mov al,20h out 20h,al iret darkelf, С адресацией я действительно намудрил. Запутался в конец.
|
|
« Последнее редактирование: 13-06-2012 12:41 от KBAC »
|
Записан
|
У тебя все получится, главное -- верить и делать. Порадоваться, когда все плохо -- легче, чем ты думаешь. В действии счастье. Вовлекая людей важно быть увлеченным чужой жизнью.
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #6 : 13-06-2012 12:46 » |
|
Все регистры ты в прерывании в любом случае должен сохранять в стеке. А потом, перед выходом из прерывания, вытаскивать из стека. Просто для 8086 это выглядит длинее. Кстати, старый обработчик имеет iret. Так что, лучше не мудрить и прыгать в него через jmp.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
KBAC
|
|
« Ответ #7 : 13-06-2012 13:09 » |
|
Finch, понятно что он имеет iret. call - в случае если надо его вызвать перед тем, как свой код сработает. И зачем мне сохранять все регистры, если я не пользуюсь всеми?
|
|
|
Записан
|
У тебя все получится, главное -- верить и делать. Порадоваться, когда все плохо -- легче, чем ты думаешь. В действии счастье. Вовлекая людей важно быть увлеченным чужой жизнью.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #8 : 13-06-2012 13:16 » |
|
И зачем мне сохранять все регистры, если я не пользуюсь всеми? А ты понимаешь, что такое прерывание? (С точки зрения состояний вычислительного процесса.)
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
KBAC
|
|
« Ответ #9 : 13-06-2012 13:19 » |
|
Dimka, расскажи? Основную мысль, что ты хотел этим вопросом мне сказать.
|
|
« Последнее редактирование: 13-06-2012 13:35 от KBAC »
|
Записан
|
У тебя все получится, главное -- верить и делать. Порадоваться, когда все плохо -- легче, чем ты думаешь. В действии счастье. Вовлекая людей важно быть увлеченным чужой жизнью.
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #10 : 13-06-2012 13:50 » |
|
С точки зрения текушего процесса, прерывание это по типу дубинкой по башке. Вот и нужно делать так, чтобы было наиболее безболезнено. По крайней мере, те регистры, которые используются, нужно экранировать. Кстати, регистр флагов также. А все экранируются, как зашита от забывчивости. Ты можеш добавлять и править код в последствии, И о данной особенности кода, что у тебя не все регистры заикранированы, можеш запросто забыть.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Sla
|
|
« Ответ #11 : 13-06-2012 15:06 » |
|
Смотри... прерывание приходит в ЛЮБОЙ момент. Прерывается вычислительный процесс. Чтобы корректно продолжить работу, необходимо запомнить состояние "вычислителя" (push), обработать прерывание, и "запустить" (pop) опять вычислитель с того места где его прервали. Когда перехватываешь аппаратное прерывание, то ... Необязательно отдавать "штатному" обработчику состояние - нужно корректно обработать. А можно отдать и штатному, но для этого нужно понимать как штатный обработчик работает. В основном все аппаратные прерывания работают с портами и оперативными регистрами. Поэтому нужно сохранять/восстанавливать именно их. зы. бывают случаи... это мы оставим для следующего поколения
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
KBAC
|
|
« Ответ #12 : 13-06-2012 15:32 » |
|
Finch, спс. Где можно прочитать как обрабатывает ядро пришедшее на запрос прерывание? Мне сегодня задали вопрос, как обрабатывает ЦП запрос на прерывание? Требовалось ответить, что цп останавливает конвейер (ждет выполнения последней задачи и больше ничего не запускает) и запускает обработку прерывания. Но так как это мне препод рассказал, то мне нужно ему в следующий раз более доходчиво объяснить как работает механизм прерывания Sla, в таком случае надо вообще все регистры, т.е. не только РОН , в стек сохранять ? И все таки не понятно, если аппаратное прерывание приходит, то pushf автоматически до моего кода будет происходить (командa int), или же мне надо в своем обработчике это проделать ?
|
|
|
Записан
|
У тебя все получится, главное -- верить и делать. Порадоваться, когда все плохо -- легче, чем ты думаешь. В действии счастье. Вовлекая людей важно быть увлеченным чужой жизнью.
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #13 : 13-06-2012 15:44 » |
|
Как раньше было Сейчас просто настолько все интегрировано, что может быть и непраильные рассуждения. Была специальная микросхемка, которая заведовала прерываниями. Насколько я помню, в 8086 было 8 внешних прерываний. Начиная с 80286 поставили 2 такие микросхемки, Получилось 16 (вернее 15, одно прерывание шло на каскадирование) внешних прерываний. Так вот, когда приходило прерывания, схемка посыла на специальный вывод процессора сигнал. Процессор, дорабатывал текушее действие. Затем слал запрос на схемку, какое именно прерывание его потревожило. Запрашивал в памяти адрес обработчика прерывания. Позиционировал CS:IP на этот адрес и запирал флаг прерывания. Дальше уже работа происходила в штатном режиме с точки зрения процессора.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #14 : 13-06-2012 15:44 » |
|
Sla, в таком случае надо вообще все регистры, т.е. не только РОН , в стек сохранять ?
Да! Все РОН, кроме SP и все сегментные, кроме SS и CS. Еще раз смотри работу команд PUSHA/POPA - тебе надо написать функциональный аналог. Регистр флагов сохранять тоже нет необходимости - для аппаратного любого прерывания он сохраняется в стеке автоматически и восстанавливается командой iret. Входная процедура: push ax push bx push cx push dx push bp push si push di mov ax, ds push ax mov ax. es push ax Выходная процедура: pop ax mov es, ax pop ax mov ds, ax pop di pop si pop bp pop dx pop cx pop bx pop ax ; iret или far jmp
|
|
« Последнее редактирование: 13-06-2012 15:57 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Sla
|
|
« Ответ #15 : 13-06-2012 16:04 » |
|
KBAC, не обязательно сохранять все. Желательно! Если ты работаешь только с аккумулятором, то зачем тебе сохранять все регистры? Вот гляди.. 1. Сохранили вектор прерывания 2. Установили свой обработчик Обработчик 1. Сохранили состояние 2. обработали 2.а Восстановили состояние 3. Вызвали старый вектор (он сам всем остальным займется мы ему доверяем) 4. Вернулись из прерывания Тут есть один момент, (давно с этим не работал) нужен ли в данном случае iret, скорей всего нужен http://www.codenet.ru/progr/dos/int_0007.phpвот здесь перехват нужной кнопки Если нужная кнопка , то обработать, иначе отдать старому обработчику Это самый простой способ зы достоверность кода не гарантирую, но память подсказывает, что правильно.
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #16 : 13-06-2012 16:43 » |
|
Sla, посмотри код в начальном посте. Тут сохранять надо все.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #17 : 14-06-2012 05:48 » |
|
И все таки не понятно, если аппаратное прерывание приходит, то pushf автоматически до моего кода будет происходить (командa int), или же мне надо в своем обработчике это проделать ?
аппаратное прерывание и команда int это, имхо, всё-же концептуально разные вещи, очень похожие, но разные, т.к. int это не вызов аппаратного прерывания, это, скорее, попытка его эмулировать. Что происходит, когда происходит аппаратное прерывание описал Finch.
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #18 : 14-06-2012 06:54 » |
|
darkelf, команда int тоже сохраняет флаги на стеке и тоже запрещает прерывания. Сверься со справочником. PIC, в том виде, в каком он был в 8086, посылал по шине номер вектора прерывания и процессор фактически выполнял команду int.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #19 : 14-06-2012 07:10 » |
|
RXL, то, что она тоже выполняет такие действия, не значит, что это одно и тоже. Всё-таки в случае аппаратного прерывания инициатором является внешнее оборудование (в данном случае PIC) и оно является асинхронным, а во втором случае - пользовательская программа, и уже назвать асинхронным это прерывание сложновато.. Хотя, возможно, в данном случае это уже ньюансы.
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #20 : 14-06-2012 08:27 » |
|
Согласен, что в аппаратном и программном прерывании политика разная, но команда одна.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
KBAC
|
|
« Ответ #21 : 15-06-2012 13:21 » |
|
Sla,То ли коменты неправильные, то ли я их неправильно понял. Что значит "кнопка вызова". Я сначала подумал, что это проверка на отпускание клавиши - но нет. И, если это не POP_KEY, то мы обрабатываем клавишу по-обычному, иначе непонятные махинации, которые ,имхо, ничего не делают. Разве что проц успеет за какие-то доли секунды (пока делаем запись нового, чтение старого и снова запись значения) что-то сделать. popup - это обратная операция push'у, я правильно понял? push ax in al,60H ;читать ключ cmp al,POP_KEY ;это кнопка вызова? je do_pop ; да, активизировать popup ; нет, уйти на исходный обработчик pop ax jmp cs:[int9_vect] ;переход на первоначальный обработчик do_pop: ;------ следующий код необходим для отработки аппаратного прерывания in al,61H ;взять значениe порта управления клавиатурой mov ah,al ; сохранить его or al,80h ;установить бит разрешения для клавиатуры out 61H,al ; и вывести его в управляющий порт xchg ah,al ;извлечь исходное значение порта out 61H,al ; и записать его обратно mov al,20H ;послать сигнал "конец прерывания" out 20H,al ; контроллеру прерываний 8259 ;------ дальше - прочие проверки, и наконец - активизация popup
|
|
|
Записан
|
У тебя все получится, главное -- верить и делать. Порадоваться, когда все плохо -- легче, чем ты думаешь. В действии счастье. Вовлекая людей важно быть увлеченным чужой жизнью.
|
|
|
Sla
|
|
« Ответ #22 : 15-06-2012 14:01 » |
|
>Что значит "кнопка вызова" Та ничего не значит. Пример условный Прочитали содержимое 60-го порта Если там лежит нужный код (кнопка вызова) то обработать ее, иначе отдать все старому обработчику.
;послать сигнал "конец прерывания ; контроллеру прерываний 8259
Пока не "пошлем" прерываний не будет
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
KBAC
|
|
« Ответ #23 : 17-06-2012 10:03 » |
|
Что-то никак не могу починить свой код. Вот он новый. .model small .stack 256d .data old_handler_offset dw ? old_handler_seg dw ? buffer db 10 dup (?) endl db 0Ah, 0Dh, '$'
.code start: main proc assume cs:_text mov ax,@data mov ds,ax call int9_change ; exchange old_handler to my_handler jmp $ call progover main endp
;===================== ; my interrupt handler ;===================== my_handler_int9 proc push ax push bx push dx push cx push bp push si push di push es push ds in al,60h and al,7Fh cmp al,01h je progover pop ds pop es pop di pop si pop bp pop cx pop dx pop bx pop ax jmp dword ptr old_handler_offset my_handler_int9 endp
;================= ; dos exit proc ;================= progover proc call int9_restore mov ax,4c01h ; quit dos with 01 code int 21h progover endp
;======================= ; restore old_handler ;======================= int9_restore proc push ds push dx push ax mov ax,2509h mov dx,old_handler_seg mov ds,dx mov dx,old_handler_offset int 21h pop ax pop dx pop ds ret int9_restore endp
;================================ ; change interrupt handler ;================================ int9_change proc push ax push bx push dx push ds push es ; get old_handler mov ax,3509h ; ah = 35, al = 9 (irq1) int 21h ; get old_handler offset in es:bx ; remember old_handler's offset mov old_handler_offset,bx mov old_handler_seg,es ;write my_handler offset to vector's table ; new offset in ds:dx mov ax,2509h mov dx,seg my_handler_int9 mov ds,dx lea dx,my_handler_int9 pushf cli ; stop interrupting int 21h popf ; continue interrupting pop es pop ds pop dx pop bx pop ax ret int9_change endp
end start Интересует как правильно делать far jmp. т.е. когда я пишу jmp old_handler_offset ассемблер должен видеть, что первое слово содержит смещение не из сегмента, где сама команда jmp и берет селектор сегмента из второго слова? Еще я не уверен, что правильно запоминаю адрес старого обработчика. Потому что как только я пытаюсь сделать jmp моя прога виснет. Еще не понятно чем отличаются следующие записи mov eax,dword ptr es:[87h*4] mov eax,dword ptr es:87h Понятно, что адресацией. Как я понимаю: в первом случае мы берем двойное слово, хранящееся по смещению es + 87; а во втором у нас идет автоматическая подстановка ассемблером операнда в код. Но какая разница? И зачем писать 87h * 4, если написано dword ptr? ================== С far jmp более менее разобрался. Обновил код. Теперь не заружается старый обработчик. Т.е. когда я возвращаюсь в дос, то клава не работает - на консоле не выводятся символы.
|
|
« Последнее редактирование: 17-06-2012 11:47 от KBAC »
|
Записан
|
У тебя все получится, главное -- верить и делать. Порадоваться, когда все плохо -- легче, чем ты думаешь. В действии счастье. Вовлекая людей важно быть увлеченным чужой жизнью.
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #24 : 17-06-2012 17:01 » |
|
KBAC, извини, но ты какой-то бред несешь. Сам написал и сам не понимаешь, чего написал. Не говоря уже про грамматику. Ты хоть знаешь, что надо получить? Искал описание синтаксиса твоего ассемблера (компилятора)?
|
|
« Последнее редактирование: 17-06-2012 17:12 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
KBAC
|
|
« Ответ #25 : 17-06-2012 19:56 » |
|
Я уже все сам доделал. Всем спасибо. На каждую кнопочку генерится разный звук теперь. Осталось лишь понять почему при первом нажатии на кнопку клавиатуры идет щелкающий звук, как будто колонки включаются и сразу отключаются, а после уже программа адекватно на все реагирует. .model small .stack 256d .data old_handler_offset dw ? old_handler_seg dw ? timer_channel_0 EQU 40h timer_channel_2 EQU 42h timer_ManageRegister EQU 43h loudspeaker_ManageRegister equ 61h loudspeaker_lngt equ 1000 ; table notes do_1 dd 4591EEh .code start: main proc assume cs:_text mov ax,@data mov ds,ax call int9_change ; exchange old_handler to my_handler jmp $ call progover main endp
;===================== ; my interrupt handler ;===================== my_handler_int9 proc push ax push bx in al,60h push ax mov bx,ax ; bx uses in Bdeni and al,80h jnz key_pop call Bdeni key_pop: pop ax and al,07Fh ; get clear scan-code of key cmp al,01h ; if esc pushed je progover mov al,20h ; end out 20h,al ; of interrupt pop bx pop ax ; jmp dword ptr old_handler_offset
iret my_handler_int9 endp
;================= ; dos exit proc ;================= progover proc mov al,20h ; end out 20h,al ; of interrupt call int9_restore mov ax,4c01h ; quit dos with 01 code int 21h progover endp
;======================= ; restore old_handler ;======================= int9_restore proc push ds push dx push ax mov ax,2509h lds dx,dword ptr old_handler_offset ; mov dx,word ptr old_handler_seg ; mov ds,dx ; mov dx,word ptr old_handler_offset int 21h pop ax pop dx pop ds ret int9_restore endp
;================================ ; change interrupt handler ;================================ int9_change proc push ax push bx push dx push ds push es ; get old_handler mov ax,3509h ; ah = 35, al = 9 (irq1) int 21h ; get old_handler offset in es:bx ; remember old_handler's offset mov word ptr old_handler_offset,bx mov word ptr old_handler_seg,es ;write my_handler offset to vector's table ; new offset in ds:dx mov ax,2509h mov dx,seg my_handler_int9 mov ds,dx lea dx,my_handler_int9 pushf cli ; stop interrupting int 21h popf ; continue interrupting pop es pop ds pop dx pop bx pop ax ret int9_change endp ;=================== ; Beep ; input - bx = key code ; ; each channel ticks with the same rate ; v = 1,19318 MHz ; i.e v/(Amount of needed ticks) = requied freaquency ;=================== Bdeni proc push ax push di push bp xor di,di xor bp,bp and bx, 07fh ; clear scan-code ; programming timer for channel 2 ;manage string: SC RW M BCD mov al, 10110110b out timer_ManageRegister,al ; send to chan mov ax,0100h ; the higher val the lower sound mul bx out timer_channel_2,al mov al,ah out timer_channel_2,al ; turning on loudspeaker in al,loudspeaker_ManageRegister or al,03h ; last two bites is 1 for channel 2 and for loudspk out loudspeaker_ManageRegister, al ; delay for not immediately turning off of ldspk mov bp,00h ; little part mov di,0ffh ; big part call delay1 ; turning off loudspeaker in al,loudspeaker_ManageRegister and al,11111100b ; last two bites is 0 out loudspeaker_ManageRegister, al pop bp pop di pop ax ret Bdeni endp
;==================== ; with help of counter-latch-command ; input - di:bp (length of signal) ;==================== delay1 proc push ax push bx push cx push dx push si xor ax,ax ; latch of CE out timer_ManageRegister,al
in al, timer_channel_0 ; Chtenie tekyshego znacheniya schetchika mov ah, al in al, timer_channel_0
xor cx,cx ; for delta LEAST meaning word xor si,si ; for delta MOST meaning word LOAD_NEW_VAL: mov bx,ax ; old val to bx xor ax,ax ; latch of CE out timer_ManageRegister,al
in al, timer_channel_0 mov ah, al in al, timer_channel_0 ; new val to ax cmp ax,bx je LOAD_NEW_VAL ; means no ticks there are yet ja CMP2 jb CMP3
CMP2: ; ax > bx ; find delta mov dx, 0ffffh ; high value of counter sub dx,ax add dx,bx add cx,dx jo OVERLOAD_CX
start_cmp: jmp CMP_delta_delay CMP3: ; ax < bx mov dx,bx sub dx,ax add cx,dx jo OVERLOAD_CX
CMP_delta_delay: cmp di,0 ; di > 0 ? je DI0 _DI: cmp di,si ; cmp more signed word of delay and delta jb end2 ; delay < si je CMP_cx_bp ; di = si ja LOAD_NEW_VAL
DI0: ; di = 0 cmp si,0 jne end2 CMP_cx_bp: cmp bp,cx ; cmp delay delta referently ja LOAD_NEW_VAL jb end2 je LOAD_NEW_VAL
OVERLOAD_CX: inc si ; most signed word +=1 jmp start_cmp end2: pop si pop dx pop cx pop bx pop ax ret delay1 endp
end start
|
|
« Последнее редактирование: 17-06-2012 20:01 от KBAC »
|
Записан
|
У тебя все получится, главное -- верить и делать. Порадоваться, когда все плохо -- легче, чем ты думаешь. В действии счастье. Вовлекая людей важно быть увлеченным чужой жизнью.
|
|
|
|