Соединение объектных модулей в головной - Assembler
Формулировка задачи:
Здравствуйте. Есть программа, которая написана в одном объектном модуле, и есть необходимость разделить ее на несколько модулей. В итоге из одного модуля получилось 3, public и extrn были прописаны в нужных местах (как мне кажется). Но при компиляции всего этого добра в основную программу, она стала работать неправильно. По идее, на экран должно выдаваться текущее системное время (что она и делала ранее), а вместо этого на экране непонятные символы. Что не так? Чего не хватает в каждом модуле? Собстна, вот код.
модуль t1.asm
модуль t2.asm
и модуль t3.asm
data segment public exit db 0 ;переменная выхода tick db 0 ;таймер 1 Сh clock_out db 0 ;переменная таймера old_cs_1ch dw ? ;старый адрес 1ch old_ip_1ch dw ? public exit, tick, clock_out extrn NEW_1CH extrn CLS extrn OUT_CLOCK data ends code segment public assume cs:code, ds:data start: ;НАЧАЛО ОСНОВНОЙ ПРОГРАММЫ mov ax, data mov ds, ax mov ah, 35h mov al, 1Ch int 21h mov old_ip_1ch, bx ;сохранение старого прерывания 1ch в переменную mov old_cs_1ch, es push ds ;сохранение дс в стек mov dx, offset NEW_1CH ;записываем в dх и ах адрес нового прерывания ah mov ax, seg NEW_1CH mov ds, ax ;сохраняем данные о новом прерывании mov ah, 25h ;вызов нового прерывания mov al, 1Ch int 21h pop ds ;возвращаем из стека mov ax, data mov ds, ax mov ax, 0B800h ;переход в видеопамять mov es, ax call CLS ;вызов процедуры очистки экрана mov al,':' ;вывод двоеточия на экран mov ah, 10001111b mov es:[74*2], ax mov es:[77*2], ax kl: ;основной цикл программы cmp exit, 0 ;сравнение для выхода jne quit ;если не равно - выход cmp clock_out, 0 ;сравнение для вывода времени jne kl ;если не меньше то call OUT_CLOCK ;вызов процедуры вывода времени jmp kl quit: call CLS ;опять вызов очистки mov dx, old_ip_1ch ;возвращаем старое прерывание mov ax, old_cs_1ch mov ds, ax ;запуск старого прерывания mov ah, 25h mov al, 1Ch int 21h mov ax, 4c00h int 21h code ends end start
data segment public data ends code segment public assume cs:code, ds:data public OUT_CLOCK OUT_CLOCK proc far ;процедура вывода времени push ax push ds push es mov ax, data mov ds, ax mov ax, 0B800h ;вход в видеопам¤ть mov es, ax mov ah, 2h ;вызов системного времени int 1Ah mov al,ch ;перемещаем в аl часы and al,00001111b ;отдел¤ем единицы часов (последние 4 цифры) add al,48 ;перевод часов в аски символы mov ah, 00001111b ;перемещаем в ah байт атрибутов mov es:[73*2], ax ;в 73 ¤чейку перемещаем единицы mov al,ch ;перемещаем дес¤тки часов shr al,4 ;отдел¤ем дес¤тки часов (первые 4 цифры) add al,48 mov es:[72*2], ax ;вывод их mov al,cl; единицы минут and al,00001111b add al,48 dec ah ;мен¤етс¤ цвет mov es:[76*2], ax mov al,cl ;дес¤тки минут shr al,4 add al,48 mov es:[75*2], ax mov al,dh ;единицы секунд and al,00001111b add al,48 dec ah mov es:[79*2], ax mov al,dh ;дес¤тки секунд shr al,4 add al,48 mov es:[78*2], ax pop es pop ds pop ax ret ;возвращение обратно OUT_CLOCK endp code ends end
data segment public extrn tick: byte extrn exit: byte extrn clock_out: byte data ends code segment public assume cs:code, ds:data public NEW_1CH NEW_1CH proc far ;было near новое прерывание 1ch push ax ; ввод регистров в стек push bx push cx push dx push ds push es mov ax, data mov ds, ax mov ax, 40h ;вход в буфер клавиатуры mov es, ax ; mov ax, es:[1ch];в ах адрес хвоста буфера mov bx, es:[1ah];в ¬х адрес головы буфера cmp bx, ax ;сравнение головы и хвоста jne m5 ;если не равно, то переход jmp back ; иначе выход из прерывани¤ m5: mov al, es:[bx] ; проверка символа в буфере mov es:[1ch], bx ; очистка буфера клавиатуры cmp al, 30h ;сверка с кодом клавиши 0 jnz ticker ;если не равно то переход mov exit, 1 ;>>программа выключаетс¤ jmp back ticker: inc tick ;увеличение счетчика тиков таймера cmp tick,18 ;сравнение с секундой jl back ;если меньше, то выход mov tick, 0 ;если больше, то обнул¤етс¤ счетчик mov clock_out, 1 ;переход на вывод времени back: pop es ;возвращение регистров из стека pop ds pop dx pop cx pop bx pop ax iret NEW_1CH endp ;конец прерывани¤ public CLS CLS proc far ;было near процедура очистки экрана push cx push ax push si xor si, si ;обнул¤ем регистр mov ah, 7 ;перемещаем цвет в атрибут mov al, '' ;перемещаем пустой символ в ал mov cx, 2000 ;перемещаем в цэих количество ¤чеек на экране CL1: mov es:[si], ax ;цикл очистки экрана inc si inc si loop CL1 pop si pop ax pop cx ret CLS endp code ends end
Решение задачи: «Соединение объектных модулей в головной»
textual
Листинг программы
data segment public public exit, tick, clock_out exit db 0 ;переменная выхода tick db 0 ;таймер 1 Сh clock_out db 0 ;переменная таймера old_cs_1ch dw ? ;старый адрес 1ch old_ip_1ch dw ? data ends stack segment public db 100h dup(?) stack ends code segment public assume cs:code, ds:data, ss:stack extrn NEW_1CH : far extrn CLS : far extrn OUT_CLOCK : far start: ;НАЧАЛО ОСНОВНОЙ ПРОГРАММЫ mov ax, data mov ds, ax
Объяснение кода листинга программы
- Объявлены переменные: — exit (db 0) - переменная выхода; — tick (db 0) - таймер 1 Сh; — clock_out (db 0) - переменная таймера; — old_cs_1ch (dw ?) - старый адрес 1ch; — old_ip_1ch (dw ?) - старый адрес 1ch.
- Задано начало сегмента данных: mov ax, data.
- Переменная ds установлена в значение ax: mov ds, ax. Выше представлен список до 20 элементов, как было указано в задании. Если в коде есть ещё элементы, то их номера и названия переменных не указаны.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д