Поиск по сайту:


«Assembler IBM PC 9. Лабораторная работа № 4. Преобразование форматов числовых данных в операциях ввода-вывода»

Файл: 4 КБ
Поделиться:

9.1. ЦЕЛЕВЫЕ УСТАНОВКИ

·     Программирование операций преобразования чисел с произвольным основанием из ASCII-формата в двоичный код и наоборот.

·     Освоение принципов многомодульного программирования.

9.2. МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

Для обеспечения высокой производительности процессора при выполнении им арифметико-логических операций над числовыми данными используется их двоичное представление, однако, все данные, поступающие в машину с клавиатуры или выводимые с процессора на принтер или экран дисплея, представляются в кодах ASCII. Следовательно, одной из основных функций процессора является преобразование внешнего формата данных во внутренний двоичный формат и наоборот – из двоичного формата в коды ASCII.

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

9.2.1. ПРЕДСТАВЛЕНИЕ ЗНАКОВЫХ И БЕЗЗНАКОВЫХ ЧИСЕЛ 
В 16-РАЗРЯДНОМ КОМПЬЮТЕРЕ

В вычислительной технике принято считать отрицательными все числа, у которых старший (знаковый) бит равен 1, т. е. в 16-разрядном компьютере это соответствует числам в диапазоне 8000h...0FFFFh. При этом отрицательные числа записываются в дополнительном коде. Положительные числа 0000h ... 7FFFh имеют нулевой старший бит. В табл. 4.1 представлены числа из отмеченных выше диапазонов, которые могут быть определены в сегменте данных программы с помощью директивы DW.

Таблица 4.1

Представление чисел в 16- разрядном компьютере

Десятичное число

8-ричные и 16-ричные числа

Представление чисел в памяти, (hex)

Примечание

65535

...

32768

177777q=FFFFh

...

100000q=8000h

FFFF

...

8000

1

32767

...

127

...

1

0

77777q=7FFFh

...

177q=7Fh

...

1q=1h

0

7FFF

...

007F

...

0001

0000

2

-1

...

-128

...

-32768

-1q=-1h

...

-200q=-80h

...

-100000q=-8000h

FFFF

...

0080

...

8000

3

-32769

...

-65535

-65536

-100001q=-8001h

...

-177777q=-FFFFh

-200000q=-10000h

7FFF

...

0001

0000

4

 

Определим основные области представления чисел в табл. 4.1: 1 – область старших беззнаковых чисел, 2 – область младших беззнаковых чисел или положительных знаковых чисел, 3 – область отрицательных знаковых чисел, 4 – "квази-область" положительных чисел. Пользоваться этой формой задания чисел, допускаемой ассемблером, не рекомендуется.

В заключение отметим, что знак числа условен. Одно и то же число 0FFFFh может рассматриваться как максимальное число, а в другом – как отрицательное число –1, представленное в дополнительном коде. Таким образом, знак числа является характеристикой не самого числа, а способа его обработки.

9.2.2. ПРЕОБРАЗОВАНИЕ ASCII-КОДОВ ЧИСЕЛ С ПРОИЗВОЛЬНЫМ ОСНОВАНИЕМ 
В ДВОИЧНОЕ ЧИСЛО

Задания к лабораторной работе предусматривают использование чисел с различным основанием (2, 8, 10 и 16), поэтому здесь рассматривается способ, не зависящий от основания системы счисления. Преобразование числовых ASCII-строк в двоичное число обычно реализуется в два этапа. На первом этапе каждая ASCII-цифра (байт) преобразуется в неупакованный формат со старшей нулевой тетрадой, а затем, на втором этапе, цепочка неупакованных байтов преобразуется в число по правилу Горнера.

Наиболее просто реализуется первый этап для чисел с основанием P, равным 2, 8, и 10, и несколько усложняется для основания P = 16.

Из табл. 4.2 следует, что в последнем случае при переходе от ASCII-кода цифры к двоичному коду цифры (младшая тетрада) необходимо предварительно выполнить операцию сравнения на принадлежностьASCII-кода к цифре или прописной букве (A, B, ...F). В первом случае выполняется операция вычитания с числом 30h, а во втором – с числом 37h.

Таблица 4.2

Таблица ASCII- кодов цифр

Цифра (символ)

0

1

 

9

A

 

F

16-теричное значение

ASCII- кода символа

30

31

 

39

41

 

46

Неупакованный

формат (младшая тетрада)

0000

0001

 

1001

1010

 

1111

 

 

Реализацию схемы Горнера на втором этапе для n-разрядного числа А = anan-1...a1 с основанием Р можно представить в следующем виде:

anan-1...a2a1=((...(0 * P + an)P + an-1)P +...+a2)P + a1.

 

 
  Подпись: Неупакованный формат	Схема Горнера	Двоичное число
02 03 07	(((0*10) + 02)*10 + 03)*10 + 07	11101101


Преобразование начинается с самой старшей цифры числа и состоит из n циклов, каждый из которых использует две операции: умножение на основание системы счисления P промежуточного результата (первый промежуточный результат равен 0) с последующим прибавлением к нему двоичного кода (байта) следующей младшей цифры преобразуемого числа.

 

Пример преобразования десятичного числа: 237(10) = 11101101(2).

Рассмотренный алгоритм преобразования десятичного ASCII-числа в двоичное число реализован в программе, представленной в листинге 4.1.

Листинг 4.1. Преобразовать знаковое десятичное ASCII-число из буфера (6 байт = знак + 5 цифровых разрядов) по адресу в BX в 16-разрядное двоичный код в регистре AX.

Comment /*

Вход:     Знаковое десятичное ASCII-число в буфере байтового типа с начальным адресом в BX,

              CX -количество ASCII-символов числа, включая знак '-'.

Расположение числа в буфере: в первом байте буфера располагается старший цифровой разряд положительного числа или знак "минус" отрицательного.

Выход:       AX -16-разрядное двоичный код в регистре AX,

              Флаг CF=1, если преобразуемое число больше 32767 или меньше -32768, иначе CF=0.    */

proc                 #dec_bin

                        cmp [byte bx],'-'        ;Отрицательное число?

                        jne positive

                        inc bx                        ;Продвинем указатель и

                        dec cx                       ;уменьшим счётчик цикла

                        call conv                    ;Преобразуем модуль отрицательного десятичного числа.

;На выходе: ax – двоичный код,

;сf=1, если преобразуемое число превышает значение 65535 (т.е. регистр ax переполнится в процессе преобразования)

                        jc overflow                ;Число > 65535?

                        cmp ax,32768          

                        ja overflow                ;Число >32768

                        neg ax                       ;Сформируем дополнительный код

                        js good                      ;Закончим преобразование

positive:            call conv                    ;Преобразуем модуль положительного десятичного числа.

                        jc overflow                ; Число > 65535?

                        cmp ax,32767

                        jbe good                    ;Число< 32767

overflow:          stc                             ;cf=1

                        jmp n_good               ;Выйдем из преобразования

good:               clc                             ;cf=0

n_good:            ret

endp                #dec_bin

proc                 conv                          ;

                        push dx di

                        xor ax,ax                   ;Очистим регистр двоичного числа

                        mov di,10                  ;10- основание системы счисления

cycl:                 mul di                        ;dx:ax = ax*10

                        jc over_flow              ;Переход, если CF=1

                        mov dl,[bx]                ;Выберем очередную ASCII-цифру

                        sub dl,30h                 ;Образуем двоичное число

                        add ax,dx                  ;Промежуточная сумма

                        jc over_flow              ;Переход, если CF=1

                        inc bx

                        loop cycl                   ;Продолжим, если cx>0

                        clc                             ;Нет, сбросим флаг CF=1

over_flow:        pop di dx

                        ret

endp                conv

9.2.3. ПРЕОБРАЗОВАНИЕ ДВОИЧНОГО ЧИСЛА В ASCII-СТРОКУ ЧИСЛА 
ПО ПРОИЗВОЛЬНОМУ ОСНОВАНИЮ

Данное преобразование представляет собой процесс обратный предыдущему. На первом этапе происходит формирование младших двоичных тетрад для соответствующих ASCII-цифр (символов), навтором – получение собственно ASCII-кодов.

Первый этап реализуется путём последовательного использования операции деления исходного двоичного числа и его частных на основание соответствующей системы счисления P. Полученные остатки и представляют собой двоичные тетрады соответствующих байтов ASCII-кодов (первый остаток определяет младшую цифру преобразуемого числа, последний – старшую). Цикл деления, в котором формируется нулевое значение частного, означает конец преобразования.

Второй этап преобразования сводится к выполнению операции сложения полученных остатков с числом 30h (Р = 2, 8, 10 и, выборочно, для формирования ASCII-кодов младших цифр 16-теричного числа). Для формирования ASCII-символов A,B,...,F используется число 37h. Чтобы не заниматься хранением промежуточных результатов первых этапов, рекомендуется в каждом цикле преобразования объединять оба этапа (прямого или обратного).

 

 
  Подпись:  Номер шага деления
 числа и его частных 	Частное	Остаток	ASCII- код
 на основание 10
1	(((0*10)+02)*10 + 03	07	37h (Мл. байт)
2	((0*10) + 02)	03	33h
3	0	02	32h (Ст. байт)
Десятичное число в ASCII-формате: 32 33 37.


Пример преобразования двоичного числа в десятичное: 11101101(2)=237(10).

 

Рассмотренный алгоритм преобразования двоичного числа в десятичное ASCII-число реализован в программе, представленной в листинге 4.2.

Листинг 4.2. Подпрограмма преобразования 16-битового двоичного дополнительного кода из регистра ах в десятичное ASCII-число со знаком в буфере dec_buf (знак+5цифр). Адрес буфера находится в регистре bx.

Comment /*

Вход:        ax – 16-битовый двоичный дополнительный код,

                 bx – адрес буфера dec_buf десятичного ASCII- числа размером 6 байт.

Выход:     десятичное ASCII- число в буфере dec_buf (знак+5цифр),    

                 ax – сохраненный двоичный дополнительный код.

Дополнительные условия: младший разряд десятичного ASCII -числа должен располагаться в последнем, старшем по адресу, байте буфера.*/

Proc                     Bin_#dec

                            push dx di cx

                            push ax                               ;Сохраним знак преобразуемого числа

                            mov cx,6                             ;Размер буфера в байтах

Blank:                   mov [byte bx],' '                  ;Очистим буфер, т.е. заполним его пробелами

                            inc bx

                            loop Blank

                            dec bx                                 ;Установим адрес последнего элемента буфера

                            mov di,10                            ;Введём основание десятичной системы счисления

                            or ax,ax                               ;Установим флаг знака SF

                            jns trans                              ;Перейдём к преобразованию, если SF=0

                            neg ax                                 ;Изменим знак

trans:                    sub dx,dx                            ;Сделаем dx=0

                            div di                                   ;ax=quot(dx:ax/10), dx=rem(dx:ax/10)

                            add dl,'0'                             ;Сформируем десятичную ASCII-цифру

                            mov [byte bx],dl                  ;Занесём в буфер

                            dec bx                                 ;Движение назад

                            or ax,ax                               ;Преобразование закончено?

                            jnz trans                              ;Повторить, если АХ>0

                            pop ax                                ;Восстановить исходное число,

                            or ax,ax                               ;с целью определения его знака

                            jns out_ trans                       ;Выходим из подпрограммы, если SF=0

                            mov [byte bx],'-'                  ;Запишем знак '-' для отрицательного числа

                            pop cx di dx

out_trans:              ret

Endp                    Bin_#dec

                            End

9.2.4. ЗАДАНИЕ К РАБОТЕ. ПОРЯДОК ВЫПОЛНЕНИЯ

ВАРИАНТЫ 1-7 (табл. 4.3).

Таблица 4.3

Варианты заданий 1-7

Вариант

Система счисления

Выполняемая операция над байтами ASCII числа

Ввод с клавиатуры

Вывод на экран

1

восьмеричная

16-разрядный двоичный код,  восьмеричная,  десятичная

Циклический сдвиг вправо

на 1 байт

2

восьмеричная

16-разрядный двоичный код,  восьмеричная, шестнадцатеричная

Циклический сдвиг влево на

1 байт

3

десятичная

16-разрядный двоичный код,

десятичная,  восьмеричная

Определить байт с наибольшимASCII-кодом

4

десятичная

16-разрядный двоичный код,

десятичная,  восьмеричная

Определить байт с наименьшимASCII-кодом

5

десятичная

16-разрядный двоичный код,  десятичная,  шестнадцатеричная

Произвести реверс байтов

ASCII числа

6

шестнадцатеричная

16-разрядный двоичный код, шестнадцатеричная,  восьмеричная

Расположить цифры числа по

возрастанию

7

шестнадцатеричная

16-разрядный двоичный код, шестнадцатеричная,  десятичная

Расположить цифры числа по

убыванию

 

 

Последовательность действий для выполнения задания.

1.   Вводится в буфер памяти знаковое ASCII-число в заданной системе счисления (в диапазоне эквивалентному представлению от –32768 до 32767) с последующим преобразованием его в 16-разрядный двоичный дополнительный код (внутреннее представление целочисленных данных).

2.   Рассматривая исходное ASCII-число в буфере как некоторую последовательность байт, выполните над ними заданное преобразование (операцию). Результат операции (новую последовательность байт) вывести на экран.

3.   Двоичный дополнительный код преобразуется в числовой ASCII-формат для различных оснований с последующим выводом на экран.

ВАРИАНТЫ 8-14 (табл. 4.4).

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

Таблица 4.4

Варианты заданий 8-14

Вари-ант

Система счисления для ввода чисел

Выполняемые операторы и форма вывода результата

8

восьмеричная

+  -  *

десятичная

EQ

True/false

9

восьмеричная

/  +  -

шестнадцатеричная

NE

True/false

10

десятичная

-  *  /

двоичная

GE

True/false

11

десятичная

*  /  +

восьмеричная

GT

True/false

12

десятичная

-  *  /

шестнадцатеричная

GE

True/false

13

шестнадцатеричная

+  - *

восьмеричная

LT

True/false

14

шестнадцатеричная

/  +  -

десятичная

LE

True/false

 

 

Реализацию арифметических операторов выполнить на основе использования соответствующих арифметических команд (add, sub, imul, idiv, cwd), а логических операторов – команды cmp в сочетании с необходимыми командами условных переходов. Формат результата операции умножения при 16-раз-рядных входных сомножителях – 32 бита; внутренний формат делимого при 
16-разрядных входных числах перед выполнением операции деления должен быть подвергнут расширению со знаком до 32 бит.

СОГЛАШЕНИЯ (обязательные требования к разработке для всех 14 вариантов).

·     Программа должна включать один основной и несколько вспомогательных модулей (см. п. 9.2.5);

·     Диапазон вводимых знаковых чисел от –32768 до 32767, диапазон выводимых чисел такой же за исключением результата от выполнения операции умножения – увеличивается в два раза;

·     Ввод числа осуществляется по запросу программы. Первым вводится символ знака "–" (если число отрицательное), затем число старшими разрядами вперёд. Ввод числа заканчивается нажатием клавиши <Enter>.

·     "8"-,"10"- и "16"-тeричные вводимые и выводимые числа представляются в естественном виде (т.е. значащими цифрами модуля с указанием знака для отрицательных чисел), а двоичные – 16-разрядным дополнительным кодом. Числа должны представляться соответствующими сообщениями на экране дисплея и заканчиваться (кроме десятичных) спецификаторами оснований.

·     Ошибки ввода числа выявляются в процессе преобразования введённого числа в двоичный дополнительный код. К ним относятся:

–     ошибка переполнения, когда введённое число не укладывается в диапазон знаковых чисел 16-разрядного компьютера или, например, когда произошло переполнение при выполнении операций сложения или вычитания;

–     ввод недопустимого символа при изображении данного числа.

·     Если в ходе преобразования была обнаружена ошибка, то выводится сообщение о характере этой ошибки.

·     Если при выполнении арифметической операции произошло переполнение, то выводится соответствующее сообщение, а сам результат не выводится.

·     В конце каждого цикла преобразования программа выдаёт запрос на продолжение работы или её завершение. Управление осуществляется функциональными клавишами.

9.2.5. ВОПРОСЫ ПОСТРОЕНИЯ МНОГОМОДУЛЬНЫХ ПРОГРАММ

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

Каждая из программ лабораторной работы может быть структурно разделена на следующие функционально законченные блоки (модули):

·     преобразование чисел с произвольным основанием (8-,10-,16-теричное), представленных в ASCII-формате, в двоичное число (в дальнейшем будем применять более короткое выражение "ASCII-число с основанием P");

·     преобразование двоичного числа в ASCII-число с P основанием;

·     вычислительный модуль или модуль преобразования введённых данных по заданному алгоритму.

Каждый такой модуль оформляется в виде подпрограммы или процедуры, допускающей автономное ассемблирование (трансляцию в объектный код). В результате после трансляции будут получены объектные модули, которые объединяются в единую многомодульную программу с помощью "системообразующего" главного модуля, по ходу исполнения которого осуществляется передача управления на обработку информации от одного модуля к другому. Укажем на три основных синтаксических отличия в организации главного модуля. Только в главном модуле выполняется:

–     инициализация сегмента стека директивой Stack;

–     инициализация сегмента данных

Start:      mov ax,@data

mov ds,ax

–     каждый из модулей заканчивается директивой End, но только в главном модуле после этой директивы должна помещаться метка первой команды программы Start, с которой начинается её исполнение.

Исходный текст модуля должен иметь заголовок, в котором указывается:

–     назначение и особенности функционирования модуля;

–     описание входных данных;

–     описание выходных данных.

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

Каждый модуль может оперировать двумя типами идентификаторов: внутренними и внешними, которые определены или инициализированы в другом модуле. Все внешние имена переменных и процедур вводятся директивой

Extrn <имя>:<тип>,…,<имя >:<тип>.

Перечислим возможные значения типов.

–     Для переменных: byte, word, dword, … tbyte

–     Для числовых констант: abs (определяются через директиву присваивания =)

–     Для меток: near,far

–     Для процедур: proc

Однако, все внешние переменные (процедуры) для данного модуля, должны быть определены в каком-то другом модуле в качестве общедоступных с помощью директивы

Public <имя>, ,<имя>

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

%Title "#dec_bin.asm"

;Модуль ввода 10-тичного ASCII- числа с последующим его преобразованием в 16- разряд-

;ный двоичный дополнительный код.

;Вход: Вводимое с клавиатуры по запросу программы ASCII-число с основанием "10" в

;диапазоне от -32768 до 32767. Число вводится старшими разрядами вперёд с вводом знака "-

;" для отрицательных чисел. Ввод числа заканчивается спецификатором d.

;Выход: АХ- 16- разрядный двоичный дополнительный код,

;         CF- ошибка ввода: выход из диапазона -32768...32767, либо ввод ошибочного символа.

                     Ideal

                     Model small

                            Dataseg

In_buf                   db               8,?,8 dup(?)     ;5- разрядов +"знак "+ "спецификатор "+"CR"

                            Codeseg

                            public  ASCIIdec_bin

proc                     ASCIIdec_bin

                            ……………..

                            ret

endp                     ASCIIdec_bin

                            End

                                                              %Title "Bin_#bin.asm"

;Модуль для преобразования дополнительного кода двоичного числа из рег. АХ в ASCII-

;строку двоичных символов.

;Вход:    АХ- дополнительный код двоичного числа.

;Выход: АХ- дополнительный код двоичного числа,

;             Буфер Bin_buf – 16 байтная ASCII- строка двоичных символов.

                        Ideal

                        Model small

                        Dataseg

                            public               Bin_buf

Bin_buf                 DB                   16 dup(?)

                            Codeseg

public                   Bin_ASCIIbin

proc                     Bin_ASCIIbin

                            ……………..

endp                     Bin_ASCIIbin

                            End

                                                              %Title "Bin_#dec.asm"

;Модуль для преобразования дополнительного кода двоичного числа в ASCII- число с

;основанием "10" и спецификатором d.

;Вход:    АХ- дополнительный код двоичного числа.

;Выход:  АХ- дополнительный код двоичного числа,

;             7-байтный буфер Dec_buf с восстановленным из рег. АХ десятичным числом (знак +

;5цифр + спец-тор).

                            Ideal

                            Model small

                            Dataseg

                            public  Dec_buf

Dec_buf               db                    7 dup(?)      ;Буфер с пробелами

                            Codeseg

public                   Bin_ASCIIdec

proc                     Bin_ASCIIdec

                            ……………….

endp                     Bin_ASCIIdec

                            End

Ниже приводится один из возможных вариантов главного модуля, использующего вышеприведённые вспомогательные модули. В программе используется простой экранный интерфейс, основанный на материале лабораторной работы № 2. Вы можете его усовершенствовать на основе использования функций BIOS. Кроме того, с целью облегчения понимания работы программы объединены в одну две различные ошибки ввода – переполнение и неправильно введённый разряд числа.

%Title"#10bin10.asm"

;Демонстрационная программа ввода и преобразования десятичных знаковых чисел

;(диапазон -32768...32767) в двоичные и их обратное восстановление. Особенности

;работы с программой регламентируются сообщениями, выводимыми программой на экран.

 

              Ideal

              Model small

              Stack 256

              %nomacs                       ;Исключить из листинга макрорасширения

Macro                  out_str$ mes                   ;Макрос вывода строки mes

                            ……………..

Endm                    out_str$

Macro                  out_buf buf,number         ;Макрос вывода содержимого buf с числом байтов

                                                                  ;number

                            ……………………..

Endm                    out_buf

                            Dataseg

extrn Bin_buf:byte:16, Dec_buf:byte:7

mes1                    DB            13,10,'Введите знаковое десятичное число со специфика-'

                            DB            13,10,'тором d в диапазоне от -32768d до 32767d: $'

mes2                    DB            13,10,'Ошибка ввода: переполнение или недопустимый символ $'

mes3                    DB            13,10,'Преобразованное двоичное число в дополнительном коде:$'

mes4                    DB            13,10,'Восстановленное из двоичного кода десятичное число: $'

mes5                    DB            13,10,'Продолжаем работу <F1>, или выходим <F10>? $'

                            Codeseg

extrn ASCIIdec_bin:proc, Bin_ASCIIbin:proc, Bin_ASCIIdec:proc

Start:                    mov ax,@data                ;Установка в ds адреса

                            mov ds,ax                       ;сегмента данных

                            call screen                      ;Очистка экрана с установкой курсора

                                                                  ;в левый верхний угол (см. лаб. раб. №3)

Again:                   out_str$ mes1                 ;Вывод сообщения mes1

              call ASCIIdec_bin          ;Ввод десятичного числа с последующим преобразо-

                                                    ;ванием его в двоичный дополнительный код

              jc Abort                         ;Допущена ошибка при вводе?

              call Bin_ASCIIbin          ;Нет. Преобразовать двоичный код в ASCII- строку                                                   ;из двоичных цифр

              out_str$ mes3                 ;Вывод сообщения mes3

              out_buf Bin_buf,16         ;Вывод на экран двоичного кода введённого числа

              call Bin_ASCIIdec         ;Преобразовать двоичный код в ASCII- строку из                                           ;десятичных цифр

              out_str$ mes4                 ;Вывод сообщения mes4

                            out_buf Dec_buf,7          ;Вывод на экран восстановленного из двоичного кода                                  ;десятичного числа

;Блок управления программой. Продолжение работы – <F1>, выход -<F10>.

                            …………………

Exit                       mov ax,4C00h               ;Функция DOS 4Сh: выход из программы

                            int 21h                            ;Вызов DOS. Останов

Abort:                   out_str$ mes2                 ;Вывод сообщения mes2

                            jmp Again                       ;Повторим ввод

                            END Start                      ;Конец программы/точка входа

9.2.6. АССЕМБЛИРОВАНИЕ И КОМПОНОВКА ОТДЕЛЬНЫХ МОДУЛЕЙ В ПРОГРАММУ. 
СОЗДАНИЕ БИБЛИОТЕКИ ОБЪЕКТНЫХ МОДУЛЕЙ

Выше, в параграфе п. 9.2.5 нами была рассмотрена структура программных модулей, допускающих независимое ассемблирование с помощью команды tasm в том же формате, который первоначально был рассмотрен в первой лабораторной работе. Например, пускай имеется главный модуль main.asm и два вспомогательных x.asm и y.asm. Производим последовательное ассемблирование (порядок произвольный):

tasm main.asm

tasm x.asm

tasm y.asm

Если в вашем рабочем каталоге находятся только эти модули с расширеним .asm, то ассемблирование можно произвести одной командой tasm *.asm. Следующим шагом на пути получения единого исполняемого файла программы является сборка полученных объектных модулей с помощью команды компоновщика tlink. Если мы хотим, чтобы имя исполняемого файла совпадало с именем главного модуля (типовой случай), то он должен быть первым в списке объектных модулей (разделяются пробелами или знаком плюс):

Tlink main.obj x.obj y.obj

Для определения другого имени программы, например, calculator – имя добавляется в конце после запятой:

Tlink main.obj x.obj y.obj ,calculator

¨ ¨ ¨

Перейдём теперь к вопросу создания библиотеки объектных модулей. Если Вы в процессе разработки ассемблерных программ создали несколько хороших процедур, которые могут использоваться в других ваших программах, то данные процедуры (однородные по своему функциональному назначению) можно скомпоновать в ассемблерные модули, допускающие независимое ассемблирование. Полученный таким образом объектный модуль может быть с помощью утилиты tlib (Turbo Library) загружен в библиотеку объектных модулей (БОМ). БОМ – это дисковый файл с расширением .lib, содержащий объектные модули, прошедшие стадию ассемблирования и включающие процедуры, часто используемые при создании новых программ. Чтобы воспользоваться процедурой, входящей в состав БОМ, надо вызвать её из вашей программы командой Call, предварительно определив её в качестве внешней процедуры директивой Extrn. В процессе компоновки tlink самостоятельно просмотрит БОМ и подсоединит к программе объектный код того модуля, в котором содержится соответствующая процедура. Библиотекарь можно вызвать, набрав команду tlib в командной строке. Общая форма вызова следующая:

TLIB 4.00 Copyright (c) 1987, 1996 Borland International

Syntax: TLIB libname [/C] [/E] [/P] commands, listfile

Libname               Имя создаваемой или существующей библиотеки (полный путь)

/C                         Устанавливает чувствительность к регистру в именах

/E                    Создаёт расширенный словарь библиотечных имён. Помещается в

                            конце файла библиотеки и служит для облегчения поиска компонов-

                            щиком нужной процедуры

/Psize                    Устанавливает размер библиотечной страницы

Commands           Последовательность операторов (опций) для исполнения

+                          Добавить имя модуля в библиотеку

–                          Удалить имя модуля из библиотеки

*                          Извлечь имя модуля без удаления

–+ или +–           Заменить имя модуля в библиотеке

–* или *–            Извлечь имя модуля и удалить

listfile               Имя для файла листинга

Рассмотрим примеры работы с библиотекарем Turbo Library

·     Создание библиотеки mylib.lib из двух модулей x.obj и y.obj:

Tlib/E mylib +x.obj +y.obj

·     Создание библиотеки mylib.lib и получение листинга. Листинг – это алфавитный список модулей вместе с общими переменными (процедурами), которые в них объявлены:

Tlib/E mylib +x.obj +y.obj, mylib.lst

·     Получение листинга mylib.lst существующей библиотеки mylib.lib:

Tlib mylib, mylib.lst

·     Замена модуля x.obj на новую копию и удаление из библиотеки модуля y.obj:    Tlib mylib –+x.obj –y.obj

В случае, если модули x.obj и y.obj и есть те самые вспомогательные модули программы, главный модуль которой является main.obj, то исполняемый файл с именем main можно создать командой (обратите внимание на три запятые после имени главного модуля):

Tlink main.obj ,,, mylib.lib

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

Tlink main.obj ,,, mylib1.lib mylib2.lib

9.3. КОНТРОЛЬНЫЕ ВОПРОСЫ

1.       Изложите алгоритм преобразования ASCII-кода числа с произвольным основанием в двоичное число.

2.       Изложите алгоритм преобразования двоичного числа в ASCII-строку числа с произвольным основанием.

4.       В чём заключается концепция модульного программирования?

5.       Укажите основные синтаксические различия в организации программных модулей, принадлежащих одной программе?

6.       Как вы понимаете принцип локализации переменных в модуле и деление переменных модуля на внутренние и внешние.

7.       Как экспортировать из модуля процедуры, числовые константы и переменные в другие модули?

8.       Как импортировать в модуль процедуры, числовые константы и переменные из других модулей?

9.       Напишите команду, создающую библиотеку mta.lib из объектных модулей a.obj, b.obj и c.obj.

10.   Напишите команду создания исполнительного файла программы с главным модулем main.obj, вспомогательные модули которого находятся в библиотеке mylib.