Пример: Глобальная сеть INTERNET
Я ищу:
На главную  |  Добавить в избранное  

Главная/

Программирование, базы данных. /

Язык макроассемблера IBM PC

←предыдущая следующая→
1 2 3 4 5 6 7 8 9 10 11 12 

команде же безусловного пере­хода по адресу, находящемуся в регистре BX,

         JMP BX

абсолютный адрес перехода определяется парой CS:[BX].

    Итак,  если в ссылке на какую-то ячейку памяти не указан явно сег­ментный регистр, то этот регистр берется по умолчанию. Явно же сегмен­тные регистры надо указывать, только если по каким-то причинам регистр по умолчанию не подходит. Если, например, в команде пересылки нам надо сослаться на стек  (скажем, надо записать в регистр AH байт стека, по­меченный именем X), тогда нас уже не будет устраивать договоренность о том,  что по умолчанию  операнд команды MOV сегментируется по регистру DS, и потому мы обязаны явно указать иной регистр - в нашем случае ре­гистр SS, т.к. именно он указывает на стек:

         MOV AH,SS:X

Однако такие случаи встречаются редко  и потому в командах, как прави­ло, указываются только смещения.

    Отметим, что в MASM сегментный регистр записывается в самой коман­де непосредственно перед смещением (именем переменной, меткой и т.п.), однако  на уровне машинного языка  ситуация несколько иная.  Имеется 4 специальные однобайтовые команды, называемые префиксами замены сегмен­та  (обозначаемые как CS:, DS:, SS: и ES:).  Они ставятся перед коман­дой,  операнд-адрес которой должен быть просегментирован  по регистру, отличному от регистра, подразумеваемому по умолчанию. Например, приве­денная выше символическая команда пересылки  -  это на самом деле две машинные команды:

            SS:

            MOV AH,X

    1.4.3 Сегментирование, базирование и индексирование адресов Поскольку сегментирование адресов  - это разновидность модификации

адресов,  то в ПК адрес, указываемый в команде, в общем случае модифи­цируется по трех регистрам - сегментному, базовому и индексному. В це­лом, модификация адреса производится в два этапа.  Сначала учитываются только  базовый и индексный регистры (если они, конечно, указаны в ко­манде), причем вычисление здесь происходит  в области 16-битовых адре­сов;  полученный в результате 16-битовый адрес называется исполнитель­ным (эффективным) адресом. Если в команде не предусмотрено обращение к памяти (например, она загружает адрес в регистр), то на этом модифика­ция адреса заканчивается  и  используется  именно исполнительный адрес (он загружается  в регистр).  Если же нужен доступ к памяти,  тогда на втором этапе исполнительный адрес рассматривается как смещение и к не­му прибавляется  (умноженное на 16)  содержимое  сегментного регистра, указанного явно или взятого по умолчанию, в результате чего получается абсолютный (физический) 20-битовый адрес, по которому реально и проис­ходит обращение к памяти.

    Отметим,  что сегментный регистр  учитывается только в "последний" момент, непосредственно перед обращением к памяти,  а до этого  работа ведется только с 16-битовыми адресами. Если учесть к тому же, что сег­ментные регистры, как правило, не указываются в командах,  то можно  в общем-то считать, что ПК работает с 16-битовыми адресами.

    Как уже сказано, если в ссылке на ячейку памяти не указан сегмент­ный  регистр, то он определяется по умолчанию. Это делается по следую­щим правилам.

    1) В командах перехода  адрес перехода  сегментируется по регистру CS  и только по нему,  т.к.  абсолютный адрес команды,  которая должна быть выполнена следующей, всегда определяется парой CS:IP (попытка из­менить в таких командах сегментный регистр будет безуспешной).

Отметим, что сегментиорвание по регистру CS касается именно адреса

перехода, а не адреса той ячейки, где он может находиться. Например, в команде безусловного перехода по адресу, находящемуся в ячейке X:

         JMP X

имя X сегментируется по регистру DS,  а вот адрес перехода,  взятый из ячейки X, уже сегментируется по регистру CS.

    2) Адреса  во всех других командах,  кроме строковых  (STOS, MOVS, SCAS и CMPS), по умолчанию сегментируются:

- по регистру DS,  если  среди указанных регистров-модификаторов нет регистра BP;

- по регистру SS, если один из модификаторов - регистр BP.

    Таким образом, адреса вида A,  A[BX],  A[SI],  A[DI],  A[BX][SI] и A[BX][DI]  сегментируются по регистру DS, а адреса A[BP], A[BP][SI]  и A[BP][DI] - по регистру SS, т.е. адреса трех последних видов использу­ются для доступа к ячейкам стека.

    3) В строковых командах STOS, MOVS, SCAS и CMPS,  имеющих два опе­ранда-адреса, на которые указывают индексные регистры SI и DI, один из операндов  (на который указывает SI)  сегментируется по регистру DS, а другой (на него указывает DI) - по регистру ES.

         1.4.4 Программные сегменты. Директива ASSUME

Рассмотрим, как сегментирование проявляется в программах на MASM.

    Для того чтобы указать, что некоторая группа предложений программы на MASM образуют единый сегмент памяти,  они оформляются как программ­ный сегмент: перед ними ставится директива SEGMENT, после них - дирек­тива ENDS, причем в начале обеих этих директив должно быть указано од­но и то же имя, играющее роль имени сегмента.  Программа  же  в  целом представляет собой  последовательность таких программных сегментов,  в конце которой указывается директива конца программы END, например:


DT1 SEGMENT      ;программный сегмент с именем DT1 A DB 0

  B DW ? DT1 ENDS

   ;


    DT2 SEGMENT      ;программный сегмент DT2

      C DB 'hello'

    DT2 ENDS

   ;

   CODE SEGMENT      ;программный сегмент CODE

        ASSUME CS:CODE, DS:DT1, ES:DT2

   BEG: MOV AX,DT2

        MOV DS,AX

        MOV BH,C

        ...

   CODE ENDS

        END BEG      ;конец текста программы

    Предложения программного сегмента ассемблер размещает в одном сег­менте памяти (в совокупности они не должны занимать более 64Кб)  начи­ная с ближайшего свободного адреса, кратного 16.  Номер (первые 16 би­тов начального адреса) этого сегмента  становится значением имени сег­мента.    В MASM это имя относится к константным выражениям, а не адрес-

ным, в связи с чем в команде

       MOV AX,DT2

второй операнд является непосредственным,  поэтому в регистр AX  будет записано начало (номер) сегмента DT2, а не содержимое начальной ячейки этого сегмента.

    Имена же переменных (A, B, C)  и метки (BEG)  относятся к адресным выражениям,  и им ставится в соответствие адрес их ячейки относительно "своего" сегмента:  имени A соответствует адрес 0,  имени B - адрес 1, имени C - адрес 0, а метке BEG - адрес 0.

    Все ссылки  на предложения одного программного сегмента  ассемблер сегментирует по умолчанию по одному и тому же сегментному регистру. По какому именно - устанавливается специальной директивой ASSUME. В нашем примере эта директива определяет, что все ссылки на сегмент CODE долж­ны, если явно не указан сегментный регистр, сегментироваться по регис­тру CS,  все ссылки на DT1 - по регистру DS,  а все ссылки на DT2 - по регистру ES.

    Встретив в тексте программы ссылку на какое-либо имя (например, на имя C в команде  MOV AX,C),  ассемблер определяет, в каком программном сегменте оно описано (у нас - в DT2), затем по информации из директивы ASSUME узнает, какой сегментный регистр поставлен в соответствие этому сегменту (у нас - это ES),  и далее образует адресную пару  иэ данного регистра и смещения имени (у нас - ES:0),  которую и записывает в фор­мируемую машинную команду. При этом ассемблер учитывает используемое в ПК соглашение о сегментных регистрах по умолчанию: если в адресной па­ре, построенной им самим или явно заданной в программе, сегментный ре­гистр

←предыдущая следующая→
1 2 3 4 5 6 7 8 9 10 11 12 


Copyright © 2005—2007 «RefStore.Ru»