Компьютер - электронное устройство, которое не заменит человека до тех пор, пока не научится смеяться шуткам начальника и сваливать свои собственные ошибки на соседний компьютер.




ент при необходимости может быть вынесен за границу 64K байтного блока). В файлах COM все сегментные регистры указы- вают на начало PSP; сравните с файлами EXE, где DS и ES инициали- зируются аналогичным образом, но CS указывает на первый байт следующий за PSP.
      Для представления программы в виде файла COM требуется соблю- дение следующих правил:

      1. Не оформляйте программу в виде процедуры. Вместо этого, поместите в самое начало метку, вроде START, и завершите програм- му оператором END START.
      2. Поместите в начале программы оператор ORG 100H. Этот опера- тор указывает начало кода (т.е. устанавливает счетчик комманд).

Программы COM начинаются с 100H, что является первым байтом, следующим за PSP, поскольку CS указывает на начало PSP, которое расположено на 100H байт ниже. Для того чтобы начать выполнение с любого другого места поместите по адресу 100H инструкцию JMP.
      3. Оператор ASSUME должен устанавливать DS, ES и SS таким образом, чтобы они совпадали со значением для кодового сегмента, например, ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG.
      4. Данные программы могут помещаться в любом месте программы, до тех пор, пока они не перемешаны с кодом. Лучше начинать прог- раммы с области данных, поскольку макроассемблер может выдавать сообщения об ошибках при первом проходе, если имеются ссылки на идентификатор данных, который еще не обнаружен. Для перехода к началу кода используйте в качестве первой команды программы инст- рукцию JMP.
      5. Нельзя использовать фиксацию сегментов типа MOV AX,SEG NEW_DATA. Достаточно указания одного смещения метки. В частности, нужно опускать обычный код, используемый в начале программы для установки сегмента данных, MOV AX,DSEG / MOV DS,AX.
      6. Стековый сегмент полностью опускается в начальном коде. Указатель стека инициализируется на вершину адресного пространст- ва 64K, используемого программой (напоминаем, что стек растет вниз в памяти). В программах COM он должен быть сделан меньше чем 64K, SS и SP могут быть изменены. Имейте ввиду, что при компонов- ке программы компоновщик выдаст сообщение об ошибке, указывающее, что сегмент стека отсутствует. Игнорируйте его.
      7. Завершите программу либо инструкцией RET, либо прерыванием 20H. Прерывание 20H - это стандартная функция для завершения программы и возврата управления в DOS. Даже когда программа за- вершается инструкцией RET, на самом деле используется прерывание 20H. Это происходит потому, что вершина стека первоначально со- держит 0. При выполнении завершающей инструкции программы RET, 0 выталкивается из стека, переназначая счетчик команд на начало PSP. Находящаяся в этой ячейке функция 20H, выполняется как сле- дующая инструкция программы, вызывая передачу управления в DOS. Все это означает, что Вам не надо при старте программы помещать на стек DS и 0 (PUSH DS / MOV AX,0 / PUSH AX), как это требуется для EXE файлов.

      После того как программа сконструирована таким образом, ас- семблируйте и компонуйте ее как обычно. Затем преобразуйте ее в форму COM c помощью утилиты EXE2BIN, имеющейся в MS DOS. Если имя программы, построенной компоновщиком MYPROG.EXE, то просто введи- те команду EXE2BIN MYPROG. В результате Вы получите программный файл с именем MYPROG.BIN. Все что Вам останется после этого сде- лать - переименовать этот файл в MYPROG.COM. Вы можете также сразу использовать команду EXE2BIN MYPROG MYPROG.COM, для получе- ния файла с расширением COM.

      Низкий уровень.

      В данном примере содержится полная короткая программа, которая по установке переключателей определяет количество накопителей в машине и затем выводит сообщение на экран. Она может служить примером короткой утилиты того сорта, для которых формат COM идеален.

CSEG SEGMENT
      ORG 100H
      ASSUME CS:CSEG, DS:CSEG, SS:CSEG ;---данные START: JMP SHORT BEGIN ;переход к коду MESSAGE1 DB 'The dip switches are set for $' MESSAGE2 DB 'disk drive(s).$' ;---печать первой части сообщения BEGIN: MOV AH,9 ;функция 9 прерывания 21H - вывод
      MOV DX,OFFSET MESSAGE1 ;строки
      INT 21H ;выводим строку
      PUSH AX ;сохраняем номер функции на будущее ;---получаем установку переключателей из порта A микросхемы 8255
      IN AL,61H ;получаем байт из порта B
      OR AL,10000000B ;устанавливаем бит 7
      OUT 61H,AL ;заменяем байт
      IN AL,60H ;получаем установку переключат.
      AND AL,11000000B ;выделяем старшие 2 бита
      MOV CL,6 ;подготовка к сдвигу AL вправо
      SHR AL,CL ;сдвигаем 2 бита в начало
      ADD AL,49 ;добавляем 1, чтобы считать с 1
      ;и 48 для перевода в ASCII
      MOV DL,AL ;помещаем результат в DL
      MOV AL,61H ;должны восстановить порт B
      AND AL,01111111B ;сбрасываем бит 7
      OUT 61H,AL ;возвращаем байт ;---печать числа накопителей
      MOV AH,2 ;функция 2 прерывания 21H
      INT 21H ;печатаем число из DL ;---печать второй половины сообщения
      POP AX ;берем номер функции со стека
      MOV DX,OFFSET MESSAGE2
      INT 21H ;выводим строку
      INT 20H ;завершение программы CSEG ENDS
      END START

Глава 2. Таймеры и звук.



Раздел 1. Установка и чтение таймера.



      Все IBM PC используют микросхему таймера 8253 (или 8254) для согласования импульсов от микросхемы системных часов. Число цик- лов системных часов преобразуется в один импульс, а последова- тельность этих импульсов подсчитывается для определения времени, или они могут быть посланы на громкоговоритель компьютера для генерации звука определенной частоты. Микросхема 8253 имеет три идентичных независимых канала, каждый из которых может программи- роваться.