Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Программирование

Добавлен: 16.02.2019

Просмотров: 29250

Скачиваний: 1689

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

 

Часть 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 


background image

Глава 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 


background image

 

Часть 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). 


background image

Глава 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. Уверены, что разобраться с программой особого труда не составит. 

Как  всегда,  все  файлы-приложения  содержат  большое  количество  коммента- 

риев. И обычный совет: пользуйтесь отладчиком! 


background image

 

 

 

Глава 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 

— 

До 

Мбайт 

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 

Мбайта 

и более 

Гбайта  

и более 

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 

—