Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 29250
Скачиваний: 1689
Часть III. Файловая оболочка, вирус, резидент
254
Как правило, мнемоника команд сопроцессора имеет определенную систему,
подобную мнемоникам команд процессора: команды представляют собой со-
кращения английских слов. Например, известная вам инструкция
xchg
(от англ.
exchange — обменять). Далее приведен список некоторых команд сопроцессора:
fild
(от англ. integer load) — загрузка целого числа (в регистр сопроцессора);
fadd
(от англ. addition) — сложение;
fist
(от англ. integer store) — сохранение целого числа (в переменную в памяти);
fistp
(от англ. integer store and pop) — сохранение целого числа и выталкива-
ние его из
st(0)
.
Если в нашем примере заменить
fist Result
на
fistp Result
из приведенной
выше программы, то в
st(0)
ничего не останется. Безусловно, это достаточно
удобно. Советуем поэкспериментировать с этими операторами.
Прежде чем продолжим изучение, следует добавить еще несколько слов о рабо-
те сопроцессора.
Сопроцессор имеет специальный регистр управления. Он необходим, в частно-
сти, для указания FPU-метода округления действительного числа (вещественного
числа, числа с плавающей точкой). Например, число 23,8 может быть округлено до
24, до 23 (в зависимости от установленных битов в регистре управления) либо не
округлено вообще. Или, например, если установлен тот или иной бит определенно-
го регистра, то сопроцессор производит вычисления либо с более высокой точно-
стью, либо с более низкой — так в некоторых калькуляторах можно настроить раз-
рядность (количество знаков после запятой).
Для чего мы это затронули? Дело в том, что мы будем устанавливать биты регист-
ра управления сопроцессором
RC
, которые отвечают за округление числа. На практи-
ке все увидите...
25.3. Первая программа
с использованием сопроцессора
Теперь практикуемся на более сложном примере. В листинге 25.4 приведена за-
конченная короткая программа, которая просто складывает два целых числа с по-
мощью сопроцессора и помещает результат в переменную
Result
. Все очень про-
сто. Самое главное, что нужно сделать, — посмотреть эту программу под
отладчиком TurboDebugger, да так, чтобы были видны регистры сопроцессора при
отладке. Дополнительная и более подробная информация об использовании сопро-
цессора находится в комментариях файлов-приложений.
Листинг 25.4. Сложение двух чисел с помощью сопроцессора
.8087 ;Использовать будем инструкции процессора 8086 и сопроцессора 8087
CSEG SEGMENT
ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
ORG 100h
Глава 25. Работа с сопроцессором
255
Begin:
finit ;Инициализируем сопроцессор
fild Number1 ;st(0)=Первое число
fild Number2 ;st(1)=st(0); st(0)=Второе число
fadd ;Складываем
fist Result ;Результат сложения — в переменную Result
ret
Number1 dw 10
Number2 dw 3
Result dw ?
CSEG ENDS
END Begin
25.4. Вывод десятичного числа
с помощью сопроцессора
Возьмем простое число 1234. Естественно, в десятичном формате. На первый
взгляд кажется, что достаточно отделить четверку и вывести ее на экран, затем 3,
дальше — 2 и т. д. Например, используя известную нам команду
and
:
...
mov AX,1234
and AX,0004 ;или AND AX,0Fh
...
Либо каким-то иным способом. Но проблема в том, что число 1234 будет пред-
ставлено в шестнадцатеричном формате или — что вернее — в двоичном. Вот что
мы увидим в отладчике:
...
mov ax,4D2h
and ax,4
...
И что же мы получаем в
ax
? В первом случае (
and ax,0004
) — 0, а во втором
(
and ax,0Fh
) — 2. Почему? Вспомните информацию из прошлых глав, где мы рас-
сматривали двоичную и шестнадцатеричную системы, а также логические команды.
Так или иначе, но подобные способы не годятся. Тогда как поступить? Нужно
делить число на десять, записывая остаток от деления до тех пор, пока не останется
ноль. Вот пример:
1234/10=123 ;остаток 4
123/10=12 ;остаток 3
12/10=1 ;остаток 2
1/10=0 ;остаток 1
Часть III. Файловая оболочка, вирус, резидент
256
Получили 4321. То есть 1234 в обратном порядке. Следовательно, и выводить на
экран будем в обратном порядке.
А можно сразу в "нормальном" порядке выводить? Можно, конечно, разделить
на 1000, затем на 100, 10, ... Но ведь числа бывают разные! И начинать деление
в одном случае приходится с 1000, а в другом — с 10.
Есть другой вариант. Можно завести массив из 20—30 байт, в каждый байт мас-
сива заносить одну цифру. Однако проще всего, как уже отмечалось, делить на де-
сять до тех пор, пока делимое (т. е. выводимое число, в нашем примере — 1234) не
будет равно нулю, хоть и придется для этого выводить в обратном порядке.
Как нам разделить число на 10 и вывести остаток от деления на экран? Вот это
мы и будем делать с помощью сопроцессора. Подобный алгоритм используется
в нашей оболочке. Мы специально вынесли его в отдельный файл, чтобы вам было
удобнее разобраться, как именно работает программа.
Следует сразу отметить, что более неуклюжих алгоритмов уже не придумаешь.
Наш алгоритм будет слишком сложный и немного запутанный. Зачем же нужно
было так делать? Дело в том, что хоть этот алгоритм и далек от совершенства, но
зато он даст вам возможность понять принцип работы сопроцессора. Именно для
этого следует разобрать приведенную далее программу в отладчике TurboDebugger
или подобном ему.
Видите, сколько разных программ нужно иметь под рукой для того, чтобы пи-
сать на ассемблере! И это далеко не предел. При написании программ под опера-
ционную систему Windows необходимо будет воспользоваться известным отладчи-
ком SoftIce, работающим в реальном режиме, а также дополнительными
дизассемблерами и прочими программами. После того как вы изучите ассемблер,
вы сможете без особого труда разобраться с любой программой, написанной на
языке высокого уровня. Так или иначе, можно будет ее скомпилировать, а затем
дизассемблировать и посмотреть код.
В завершение хотелось бы обратить ваше внимание, что в файле-приложении
к этой главе вы найдете программу с именем !Coproc!.asm, которая выводит на
экран число в десятичной форме с использованием инструкций сопроцессора.
В данном файле вполне достаточно описаний, чтобы понять работу программы.
Ассемблируйте и запускайте ее под отладчиком.
25.5. Оболочка
Что теперь делает наша оболочка? Не зря мы рассматривали работу сопроцессо-
ра и вывод с его помощью десятичных чисел. Наша оболочка теперь может выво-
дить не только размер файлов, но и их длинные имена.
25.5.1. Получение и вывод длинного имени файла
Для получения и вывода длинного имени файла следует воспользоваться функ-
циями
714Eh
и
714Fh
(а не
4Eh
и
4Fh
) прерывания
21h
(листинг 25.5, рис. 25.2).
Глава 25. Работа с сопроцессором
257
Листинг 25.5. Получение длинного имени файла
...
mov ax,714Eh ;Функция поиска первого файла
;di должен указывать на буфер, куда будут записываться данные
;о найденном файле (типа DTA).
xor di,di
;на si пока не обращаем внимания.
xor si,si
;Ищем все возможные файлы. Это что-то вроде атрибутов файла
mov cx,0FFh
mov dx,offset All_files
;Маска поиска (*.*)
int 21h
;Теперь в es:di находится информация о найденном файле!
mov Handle,ax ;Номер процесса поиска файлов
...
Рис. 25.2. Чтение длинных имен файлов
Отличие функции
714Eh
еще в том, что она требует указания номера, который
мы сохраняем после вызова
714Eh
. Все остальное подробно описано в файле-
приложении (files.asm). Процедура вывода десятичных чисел находится в файле
display.asm. Уверены, что разобраться с программой особого труда не составит.
Как всегда, все файлы-приложения содержат большое количество коммента-
риев. И обычный совет: пользуйтесь отладчиком!
Глава 26
История развития ПК
В данной главе мы рассмотрим историю развития IBM-совместимых компьюте-
ров, а также продолжим писать код нашей оболочки.
26.1. Краткая история развития
IBM-
совместимых компьютеров
Каждый программист на ассемблере должен знать историю развития ПК.
В табл. 26.1 перечислены все модели IBM-совместимых компьютеров в порядке их
создания и развития.
Таблица 26.1. История развития ПК IBM PC
Процес-
сор
Тип
ОЗУ
Винче-
стер
Частота
(MГц)
Видео
Отечест-
венный
аналог
8086/8088
—
256
—640
Кбайт
10
—20
Мбайт
4,77
—8
Mono,
CGA
ЕС-1840,
1841,
1851...
80286
—
До
4
Мбайт
20
—60
Мбайт
6
—16
CGA-VGA
ЕС-1849
80386
SX/DX
4
—8
Мбайт
40
—120
Мбайт
16
—40
EGA-VGA
ЕС-1863
80486
SX/DX
4
—12
Мбайт
80
—500
Мбайт
25
—120
EGA-VGA
—
Pentium I
MMX
16
Мбайт
и более
300
—
1000
Мбайт
60
—266
VGA-sVGA
—
Pentium II
MMX
32
Мбайта
и более
4
Гбайта
и более
300
—500
sVGA
—
Pentium III
MMX SSE
64
Мбайта
и более
10
Гбайт
и более
600
—1000 sVGA
—
Pentium 4
MMX SSE
128
Мбайт
и более
40
Гбайт
и более
От 1000
sVGA
—
Intel Core
Duo, Core
2 Duo,
Core Quad
MMX
SSE I, II, III
512
Мбайт
и более
80 Гбайт
и более
От 1000
sVGA
—