Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






  • Сервис онлайн-записи на собственном Telegram-боте
    Тот, кто работает в сфере услуг, знает — без ведения записи клиентов никуда. Мало того, что нужно видеть свое расписание, но и напоминать клиентам о визитах тоже. Нашли самый бюджетный и оптимальный вариант: сервис VisitTime.
    Для новых пользователей первый месяц бесплатно.
    Чат-бот для мастеров и специалистов, который упрощает ведение записей:
    Сам записывает клиентов и напоминает им о визите;
    Персонализирует скидки, чаевые, кэшбэк и предоплаты;
    Увеличивает доходимость и помогает больше зарабатывать;
    Начать пользоваться сервисом
  • St segment stack






    dw 64 dup (?)

    St ends

    N equ 1000

    Data segment public

    A dw N dup (?)

    public A, N; Входные точки

    extrn Summa: word; Внешняя переменная

    Diagn db 'Переполнение! ', 13, 10, '$'

    Data ends

    Code segment public

    assume cs: Code, ds: Data, ss: St

    Start: mov ax, Data

    mov ds, ax

    mov cx, N

    sub bx, bx; индекс массива

    L: inint A[bx]; Ввод массива A

    add bx, type A

    loop L

    extrn Sum: far; Внешнее имя

    call Sum; Процедура суммирования

    outint Summa

    Newline

    ; А теперь вызов с ошибкой

    mov A, 7FFFh; Maxint

    mov A+2, 1; Для переполнения

    call Sum

    outint Summa; Сюда возврата не будет

    Newline

    finish; Вообще-то не нужен

    public Error; Входная точка

    Error: lea dx, T

    Outstr

    Finish

    Code ends

    end Start; головной модуль

     

    В нашем головном модуле три входные точки с именами A, N и Error и два внешних имени: Sum, которое имеет тип дальней метки, и Summa, которое имеет тип слова. Работу программы подробно рассмотрим после написания текста второго модуля с именем p2.asm.

    Comment * модуль p2.asm

    Суммирование массива, контроль ошибок

    include io.asm не нужен – нет ввода/вывода

    Используется стек головного модуля

    В конечном end не нужна метка Start

    *

    Data segment public

    Summa dw?

    public Summa; Входная точка

    extrn N: abs; Внешняя константа

    extrn A: word; Внешний адрес

    Data ends

    Code segment public

    assume cs: Code, ds: Data

    public Sum; Входная точка

    Sum proc far

    push ax

    push cx

    push bx; сохранение регистров

    xor ax, ax; ax: =0

    mov cx, N

    xor bx, bx; индекс 1-го элемента

    L: add ax, A[bx]

    jno L1

    ; Обнаружена ошибка

    pop bx

    pop cx

    pop ax

    extrn Error: near

    jmp Error

    L1: add bx, type A

    loop L

    mov Summa, ax

    pop bx

    pop cx

    pop ax; восстановление регистров

    Ret

    Code ends

    End

    Наш второй модуль не является головным, поэтому в его директиве end нет метки первой команды программы. Модуль p2.asm имеет три внешних имени A, N и Error и две входные точки с именами Sum и Summa. Так как второй модуль не производит никаких операций ввода/вывода, то он не подключает к себе файл io.asm. Оба наших модуля используют общий стек объёмом 64 слова, что, наверное, достаточно, так как стековый кадр процедуры Sum невелик.

    Разберём работу нашей программы. После ввода массива A головной модуль вызывает внешнюю процедуру Sum. Это статическая связь модулей по управлению, дальний адрес процедуры Sum будет известен головному модулю до начала счёта. Этот адрес будет расположен в формате i32 на месте операнда Sum команды call Sum.

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

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

    Здесь необходимо отметить важную особенность использования внешних адресов. Рассмотрим, например, команду

    L: add ax, A[bx]

    во втором модуле. При получении из этого предложения языка Ассемблера машинной команды необходимо знать, по какому сегментному регистру базируется наш внешний адрес A. На это во втором модуле (а только его и видит во время перевода программа Ассемблера, первый модуль недоступен!) указывает местоположение директивы

    extrn A: word; Внешний адрес

    внутри второго модуля. Эта директива располагается в сегменте с именем Data, а директива

    assume cs: Code, ds: Data

    определяет, что во время счёта на этот сегмент будет установлен регистр ds. Следовательно, адрес A соответствует области памяти в том сегменте, на который указывает регистр ds.[46] Как видим, директива assume нам снова пригодилась.

    Продолжим рассмотрение работы нашей программы. Получив управление, процедура Sum сохраняет в стеке используемые регистры (эта часть соглашения о связях выполняется), и накапливает сумму всех элементов массива A в регистре ax. При ошибке переполнения процедура восстанавливает значения регистров и передаёт управление на метку Error в головном модуле. В нашем примере второй вызов процедуры Sum специально сделан так, чтобы вызвать ошибку переполнения. Заметим, что переход на внешнюю метку Error – это тоже статическая связь по управлению, так как адрес метки известен до начала счёта. В то же время возврат из внешней процедуры по команде ret является динамической связью по управлению, так как конкретный адрес возврата в другой модуль будет помещён в стек только во время счёта программы.

    Программа Ассемблера не в состоянии перевести каждый исходный модуль в готовый к счёту фрагмент программы на машинном языке, так как, во-первых, не может определить внешние адреса модуля, а, во-вторых, не знает будущего расположения сегментов модуля в памяти. Говорят, что Ассемблер переводит исходный модуль на специальный промежуточный язык, который называется объектным языком. Следовательно, программа Ассемблер преобразует входной модуль в объектный модуль. Полученный объектный модуль оформляется в виде файла, имя этого файла обычно совпадает с именем исходного файла на языке Ассемблер, но имеет другое расширение. Так, наши исходные файлы p1.asm и p2.asm будут переводиться (или, как чаще говорят, компилироваться или транслироваться) в объектные файлы с именами p1.obj и p2.obj.

    Рассмотрим теперь, чего не хватает в объектном модуле, чтобы быть готовым к счёту фрагментом программы на машинном языке. Например, самая первая команда всех наших программ

    mov ax, Data

    должна переводится в машинную команду пересылки формата mov ax, i16, однако значение константы i16, которая равна физическому адресу начала сегмента Data в памяти, делённому на 16, неизвестна программе Ассемблера и поле операнда i16 в команде пересылки остаётся незаполненным. Таким образом, в объектном модуле некоторые адреса остаются неизвестными (неопределёнными). До начала счёта программы, однако, все такие адреса обязательно должны получить конкретные значения.

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

    · Сведения обо всех сегментах модуля (длина сегмента, его спецификация).

    · Сведения обо всех общедоступных (экспортируемых) именах модуля, с каждым таким именем связан его тип (abs, byte, word, near и т.д.) и адрес (входная точка) внутри какого-либо сегмента модуля (для константы типа abs это просто целое число).

    · Сведения о местоположении и типе всех внешних адресов модуля.

    · Сведения о местоположении всех остальных незаполненных адресов в модуле, для каждого такого адреса содержится информация о способе его заполнения перед началом счёта.

    · Другая информация, необходимая для сборки программы из модулей.

    На рис. 10.1 показано схематическое изображение объектных модулей p1.obj и p2.obj, полученных программой Ассемблера, для каждого модуля изображены его сегменты, входные точки и внешние адреса. Вся эта информация содержится в паспортах объектных модулей.[47]

    p1.obj     p2.obj
           
    St segment stack       Data segment public extrn A: word extrn N: abs public Summa: word
    Data segment public public A: word public N: abs extrn Summa: word     A N Summa A N Summa
    Code segment public Extrn Sum: far public Error: near   Sum Error   Sum Error Code segment public publicSum: far extrnError: near
           
    Рис. 10.1. Схематический вид объектных модулей с внешними адресами и входными точками.

    Обратимся теперь к проблеме сборки программы из модулей. Как мы уже упоминали, эту работу выполняет специальная системная программа, которая называется редактором внешних связей. Из этого названия хорошо видно одно из назначений этой программы – устанавливать связи между внешними адресами и входными точками модулей. Рассмотрим схему работы редактора внешних связей на нашем примере.






    © 2023 :: MyLektsii.ru :: Мои Лекции
    Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
    Копирование текстов разрешено только с указанием индексируемой ссылки на источник.