|
::Главная страница :: Assembler :: Статьи :: |
FAQ 1-10
1. Проблема в отладке программы (исходников нет, только
exe). Программа перехватывает прерывание INT 3h. При отладке в td.exe перехвата
INT 3 компьютер зависает. Отладчик конечно тоже использует это прерывание. Заменить
INT 3 на другое не удаётся, т.к. занимает один байт. Как можно выйти из положения.
Замени на NOP (90h) (Эта команда ничего не делает,
только отнимает такты процессора).
Nik
2. При написании программы типа "звездное небо"
я столкнулся с одной трудностью. Как в ассемблере сгенерировать случайное число.
Надо чтоб оно было полностью случайным. INT 2Ch не подходит, так как сотые доли
секунд периодичны и точки на экране скапливаются в линииобразных промежутках.
Вот вроде как генератор сл. чисел.
.model tiny .code .286 org 100h start: call del_old mov ax,60 call rnd call divide call print_num mov ah,1 int 16h je start ret divide: mov bx,10 mov bp,offset [num]+4 cont_div: xor dx,dx div bx add dl,'0' mov [bp],dl dec bp or ax,ax jne cont_div ret print_num: mov dx,offset num mov ah,9 int 21h ret del_old: mov di,offset num mov al,32 mov cx,5 rep stosb ret r1 dw 10050 r2 dw 30066 r3 dw 45611 rnd: mov bx,ax mov ax,r1 add ax,r2 mov r1,ax add ax,r3 mov r2,ax ror ax,1 mov r3,ax mul bx xchg ax,dx ret num db ' ',0dh,0ah,'$' end start K.A. NiCK
3. Вопрос "чайника". Что есть порт? Где находяться
порты - в отдельном чипе (проц, северный аль южный мосты) или разбросаны по
разным микрухам компа. Если можно по подробнее, что есть номер порта (номер
порта FFh и адрес ячейки памяти FFh - я знаю, суть разные вещи). И еще порт
и адрес ввода/вывода - это одно и тоже?
Во первых, разберемся, какие порты нам нужны. COM,
LPT - последовательный и параллельный соответственно:
это обыкновенные разъемы, к которым например подключаются мыша, принтер, момед(если
внешний) и тд. тна практике обычно есть 2 COM и 1 LPT порт(как устройства.).
хотя теоретически (тоесть для программ) могут быть доступны и COM4 и даже COM7.
Собственно же программа (втч твоя) работает с т.н. Портами ввода-вывода. вот
их определение из книжки: "порт i/o - 8,16 или 32-разрядный аппаратный
регистр(не путать с регистрами проца - прим. от меня), имеющий определенный
адресв адресном пространстве ввода-вывода" Номер порта - ну как объяснить?
вот десять портов (предположим) - так что им, каждому имя давать? зачем? когда
их можно просто пронумеровать 0..9. на самом деле их количество ограничено размерностью
адр. пр-ва ввода-вывода - FFFFh штук. например таймер имеет 4 порта - 40h..43h
(для различных каналов. не буду я тут схему работы таймера разбирать.). фактически,
обращаясь к портам i/o ты общаешся с устройствами почти напрямую. для этого
используются команды in и out: in <аккумулятор - eax/ax/al>, из порта
считывается байт/слово/дв.слово в аккумулятор.
out ,содержимое аккумулятора пересылается в порт N. Да. если номер порта <0FFh
то можно задавать его непосредственно, иначе - через
dx:xor ax,ax
mov dx,100h ;порт с большим номером
out dx,ax ;выводим в этот порт нолик. кроме того, для вывода/ввода не по байтам,
а строчками есть команды
ins,outs (вернее ins/insb/insw/insd и ан-но outs/...) перед вызовом их в dx
вносим номер порта, в es:di - строку для вывода, а для ins - результат будет
по адресу es:di.
Event
5. У меня к Вам вопрос по поводу динамического выделения
памяти. При использовании ДОСовской функции 48h возникает ошибка 08h (недостаточно
памяти). Хотя я пытаюсь выделить всего лишь один параграф. Может я чего не так
делаю?
Прежде, чем отводить память функцией 48h, необходимо
"урезать" память при помощи функции 4Ah. Зачем? Дело в том, что сразу
после загрузки программы (причем, любой), DOS отводит ВСЮ память этой программе.
Поэтому нам сперва нужно использовать функцию 4Ah, чтобы "урезать"
память до размеров программы, а затем только отводить блоки.
Подробней можно посмотреть как мы делаем в оболочке в рассылке по Ассемблеру
(28 выпуск).
Прилагаю кусок кода, который урезает память до размеров загруженной программы.
mov bx,offset Finish shr bx,4 inc bx mov ah,4Ah int 21h ;Ужимаем размер отведенной памяти до метки Finish .... Finish equ $ ;Самая последняя строка в программе! Отправил: Олег Калашников
6. Как убрать задержку перед началом повтором вывода
символа?(для игры)
Ответ1 (Ламерский): В документации напиать, что
в Windows Панель Управления/Клавиатура надо настроить этот параметр. Не подходит,
нужно ведь для DOS.
Ответ2 (Юзерский): Написать, как тот же параметр настроить через BIOS Setup.
Ответ3 (Программерский):
mov ax,0305h ;здесь не уверен, может 0300 ?
mov bx,0 ;bh=0 - 0,25 секунды
;bh=1 - 0,5 секунды
;bh=2 - 0,75 секунды
;bh=3 - 1,0 секунды
Int 16h
Ответ4 (наверно Хакерский:)): Написать свой обработчик прерывания int 9, отвечающего
за обработку прерываний от клавиатуры
Александр
7. Что и в какой последовательности располагается в оперативной
памяти компьютера после того, как мы его включаем? Конечно, при условии, что
в нём есть DOS.:)) Т.е. хотелось бы уяснить себе структуру расположения данных
в оперативной памяти (если это возможно, то с размерами).
Стандартная память(первые
640Кб)
00000-003FF Таблица векторов прерываний
00400-004FF BIOS DATA Area.
00500-00xxx DOS Area - Тут сидит злобный DOS.
00xxx-9FFFF User RAM - Память для пользовательских программ. (Не более 638Кб).
9FC00-9FFFF Расширение BIOS DATA Area для PS/2 мыши.
Верхняя память - UMA(384Кб)
A0000-BFFFF Video RAM - Видеопамять, 128Кб. полностью практически не используется.
С0000-DFFFF Adapter ROM или RAM - для устройств со своими модулями BIOS и специальная
область ОЗУ(?).
E0000-EFFFF свободная область, иногда System BIOS.
F0000-FFFFF System BIOS, 128Кб ROM(или flash ROM) на системной плате.
В XT используются только FE000-FFFFF.
Вот и весь первый мегабайт. Все что выше должно быть либо XMS либо EMS - памятью(под
DOS само-собой разумеется) или вообще не быть.
Александр
8. Подскажите каким образом можно вывести на экран число
из регистра или значение переменной. Пробовал выводить функцией 09h 21-го прерывания
- выводится какая-то чепуха, а хотелось бы увидеть в более понятном виде, типа
шестнадцатиричном. С выводом строк проблем нет, а вот как вывести число - непонятно.
Конечно ты увидел аброкадабру, потому что этой
функцией ты выводишь СИМВОЛ, с соответствующим кодом, а не число. Вообще-то
я не жадный -так что держи функцию. Хоть сам разберешься. После того как получишь
СТРОКУ - ты сам знаешь, что делать
HexWord proc ;AX - нужное число ;DS:SI - куда писать результат push cx push ax and ax,0F000h mov cl,12 shr ax,cl call hexasc pop ax push ax and ax,0F00h mov cl,8 shr ax,cl inc si call hexasc pop ax push ax and ax,0F0h mov cl,4 shr ax,cl inc si call hexasc pop ax push ax and ax,0Fh inc si call hexasc pop ax pop cx ret HexWord proc hexasc proc push BX mov BX, offset tblhex xlat mov [SI],AL pop BX ret tblhex db '0123456789ABCDEF' hexasc endp Александр
9. Подскажите, пожалуйста, где хранится серийный номер
винчестера. К чему лучше всего привязывать программу для защиты от записи на
другие РС ?
Серийный номер винчестера хранится в Boot Sector'е,
но читать его оттуда напрямую я не рекомендую. Есть более приятный способ: У
сервиса прерывания 21h есть функция 69h - get/set disk serial number Вот как
надо загружать регистры пр ииспользовании этой ф-ии:
AH=69h (естественно)
AL=0, если читаем серийный номер
AL=1, если пишем серийный номер
BL ->содержит диск, у которого берем или на который пишем сер. номер диски
обозначаются так:
BL=0 - текущий диск
BL=1 - drive A
bl=2 - drive B
bl=3 - drive C
ну и так далее
DS:DX = адрес структуры, куда функция вернет/возьмет информацию
Формат структуры:
+00h word уровень информации (установите равным нулю)
+02h double word серийный номер диска
+06h 11 bytes метка тома или "NO NAME ",если нету
+11h 8 bytes файловая система - "FAT12","FAT16","FAT32"
Возврашает:
CF=0 - успех
CF=1,ошибка, AX=код ошибки.
Данная функция недокументирванна.
Я думаю, что привязываться к серийному номеру вполне разумно :)
Евгений
10. Подскажите, можно ли отлаживать программу в TurboDebugere,
которая вызывается функцией 4B00 INT 21h. У меня не получается. Компьютер виснет
при попытке пошаговой отладки процедуры прерывания.
Программу которая
вызывается можно. а вот процедуру прерывания можно, но, как вы это уже заметили,
возможно все будет виснуть. просто не всегда можно остановить выполнение очередной
команды процедуры прерывания, да еще что-то свое выполнить (т.е. то, что делает
отладчик: сделать дамп памяти, показать все на экран и т.п.). это из-за того,
что в процедурах прерываний используется самый низкоуровневый доступ, т.е. порты
ввода/вывода, и поэтому послав на как-то порт команду, возможно мы должны сразу
принять ответ, отладчик об этом не заботится. можете попробовать еще отладчик
debug.exe, но скорее всего это тоже не поможет. если вам очень интересно/надо,
то лучше сделайте дамп памяти того участка, который вас интересует и дизассеблируйте
его.
BELTSY
Ассемблер?
Это просто! Учимся программировать (FAQ)
(C) Москва, 2001. Авторское право принадлежит
Калашникову О.А. Публичное размещение материала из рассылки, а также его
использование полностью или частично в коммерческих или иных подобных целях
без письменного согласия автора влечет ответственность за нарушение авторских
прав.
Составитель: Софронов П.Н. (Lonely L)
Все права сохранены
19.11.2001
Харьков 2001
© Софронов П.Н. 2001
Тематические
ссылки
|
Ваша ссылка | Ваша ссылка |
Обмен кнопками, ведение статистики, реклама. |
|||