Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

epd627

.pdf
Скачиваний:
22
Добавлен:
02.05.2015
Размер:
816.97 Кб
Скачать

Практически не так просто одновременно получить доступ к более чем 64 Кб памяти. Это связано со специфическим средством, которое называется сегментацией.

4.6.Регистры

Впроцессоре 8086 имеется несколько быстрых элементов памяти на интегральных схемах, которые называются регистрами. К регистрам процессор обращается быстрее, чем к обычной памяти.

Регистры разбиваются на четыре категории: регистр флагов, регистры общего назначения, указатель инструкций и сегментные регистры.

4.7.Регистр флагов

Этот 16-битовый регистр (flags) содержит всю необходимую информацию о состоянии процессора 8086 и результатах последних инструкций (рис. 4.1).

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

 

 

o

d

i

t

s

z

 

a

 

p

 

c

Рис. 4.1

Битовые флаги: o – флаг переполнения (другое обозначение – of); d – флаг направления, другое обозначение – df); i – флаг прерывания (if); t – флаг перехвата (tf); s – флаг знака (sf); z – флаг нуля (zf); a – флаг дополнительного переноса (af); p – флаг четности (pf); c – флаг переноса

(cf).

Если требуется знать, получен ли при вычитании нулевой результат, непосредственно после этой инструкции следует проверить флаг нуля (бит z в регистре флагов). Если он имеет ненулевое значение, то результат нулевой. Другие флаги, такие, как флаги переноса и переполнения аналогичным образом сообщают о результатах арифметических и логических операций.

Другие флаги управляют режимом операций процессора 8086.

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

Регистр флагов управляется с помощью специальных инструкций (stc, std, sti, clc, cld, cli и др.), а также с помощью арифметических и логических инструкций, модифицирующих отдельные флаги. Содержимое отдельных

21

разрядов регистра флагов влияет на выполнение инструкций (например, jz, rcr и movsb).

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

4.8. Регистры общего назначения

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

 

ax

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

 

 

ah

 

 

 

 

 

 

 

al

 

 

 

 

bx

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

 

 

bh

 

 

 

 

 

 

 

bl

 

 

 

 

cx

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

 

 

ch

 

 

 

 

 

 

 

cl

 

 

 

 

dx

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

 

 

dh

 

 

 

 

 

 

 

dl

 

 

 

 

si

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

di

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

sp

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

bp

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 4.2

Каждый регистр общего назначения может использоваться для хранения 16-битового значения в арифметических и логических операциях. Может выполняться обмен между регистром и памятью (запись из регистра в память и наоборот), между регистрами. Например, в

22

приведенном ниже фрагменте программы складывается содержимое регистров:

mov

ax,5

; загрузить в регистр ax число 5

mov

dx,9

; загрузить в регистр dx число 9

add

ax,dx

; поместить в регистр ax сумму регистров ax и dx

результат (14) сохраняется в регистре ax. Вместо регистров ax и dx здесь можно использовать регистры cx, si или любой другой регистр общего назначения. Рассмотрим каждый из них отдельно.

4.9. Регистр ax

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

Младшие 8 битов регистра ax называются также регистром al, а старшие 8 битов – регистром ah. Это удобно при работе с данными размером в байт. Таким образом, регистр ax можно использовать как два отдельных регистра:

mov ah,0

; загрузить в регистр ah число 0

mov

al,2

; загрузить в регистр al число 2, т.е. al:=2

inc

al

; нарастить содержимое al на 1, т.е. al:= al + 1 = 2+1=3

В результате в регистре al будет записано значение 3, в регистре ah будет записано значение 0 и, следовательно, в регистре ax будет также записано значение 3. Регистры bx, cx и dx могут аналогичным образом использоваться либо как один 16-битовый регистр, либо как два 8-битовых.

4.10. Регистр bx

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

mov

ax,0 ; загрузить в регистр ax число 0

mov

ds,ax

; загрузить в регистр ds число 0

mov

bx,9 ; загрузить в регистр bx число 9

mov

al,[bx]

; загрузить в регистр al содержимое адреса памяти 9

Когда bx используется в качестве указателя на ячейку памяти, то по умолчанию из-за сегментной организации памяти процессора 8086 он ссылается на нее относительно сегментного регистра ds.

23

Как и регистры ax, cx и dx, регистр bx может интерпретироваться как два 8-битовых регистра – bh и bl.

4.11. Регистр cx

Специализация регистра cx – использование в качестве счетчика. Предположим, требуется 10 раз повторить выполнение блока инструкций. Это можно сделать следующим образом:

mov cx,10 ; cx:=10 metka:

<блок инструкций, который нужно повторить>

sub

cx,1

; cx:= cx – 1 и zf:=0, если cx<>0 (т.е. cx не равен нулю)

jnz

metka

; если zf =0, переход на metka; иначе (т.е. zf=1)

;

 

выполняется команда, следующая за командой jnz metka

Инструкции между меткой metka и инструкцией jnz будут повторяться до тех пор, пока содержимое регистра cx не станет равным 0. Заметим, чтобы уменьшить содержимое cx и перейти на начало цикла metka, если регистр cx еще не равен 0, здесь используются две инструкции

-sub и jnz.

Впроцессоре 8086 используется специальная инструкция loop (инструкция цикла), которая вычитает 1 из значения регистра cx и выполняет переход, если содержимое регистра cx не равно 0. Для приведенного выше примера можно записать такой эквивалент:

mov cx,10 metka:

<блок инструкций, который нужно повторить>

loop metka

;cx:=cx-1 и, если cx<>0, переход на metka,

;

иначе (cx=0) на следующую команду

Регистр cx особенно полезен для использования в циклах и в качестве счетчика. Как и регистры ax, bx и dx, регистр cx можно рассматривать как два 8-битовых регистра – ch и cl.

4.12. Регистр dx

Регистр dx – это единственный регистр, который может использоваться в качестве указателя адреса ввода-вывода в инструкциях in и out (см. уч. пос., ч.8). Единственный способ адресоваться к портам вводавывода с 256 по 65535 – это использовать регистр dx:

mov

al,62

; al:= 62

mov

dx,1000

; dx:= 1000

out

dx,al

; вывод в порт № 1000 содержимого регистра al

Другие уникальные качества регистра dx относятся к операциям

деления

и умножения. Когда надо разделить 32-битовое делимое или

 

 

24

использовать 16-битовый делитель, старшие 16 битов делимого должны быть помещены в регистр dx. После выполнения деления остаток также сохраняется в dx. (Младшие 16 битов делимого должны быть помещены в ax. Частное от деления также будет записано в ax). Аналогично, когда перемножаются два 16-битовых сомножителя, старшие 16 битов произведения сохраняются в dx, а младшие 16 битов записываются в ax (см. п.4.65 «Деление целых чисел без знака», п.4.66 «Беззнаковое деление 16-битового значения на 8-битовое», п.4.64 «Умножение целых чисел без знака»).

Как и регистры ax, bx и сx, регистр dx можно использовать для сложения, вычитания, логических операций и операций перемещения данных и интерпретировать как два 8-битовых регистра – dh и dl.

4.13. Регистр si

Как и регистр bx, регистр si может использоваться как указатель на ячейку памяти. Особенно полезно использовать регистр si для ссылки на память в строковых инструкциях процессора 8086 (см. уч. пос., ч.4).

4.14. Регистр di

Регистр di также можно использовать в качестве указателя ячейки памяти. Так же, как и регистр si, полезно использовать регистр di для ссылки на память в строковых инструкциях процессора 8086 (см. уч. пос., ч.4) Когда регистры si и di используются в качестве указателей на ячейки памяти в других инструкциях (не строковых), то они всегда адресуются к памяти относительно регистра ds. Когда регистры si и di используются в качестве указателей на ячейки памяти в строковых инструкциях, то они адресуются к памяти относительно регистра ds и es, соответственно.

4.15. Регистр bp

Регистр bp также может использоваться в качестве указателя на ячейку памяти, но регистр bp адресуется к памяти относительно регистра ss (сегментный регистр стека).

Стек – это область памяти, в которой можно сохранять значения и из которой они могут затем извлекаться по дисциплине "последним пришел – первым ушел" (fifo). То есть последнее сохраненное в стеке значение будет первым значением, которое Вы получите при чтении из стека.

Стек располагается в сегменте памяти, описываемом регистром ss, а текущее смещение вершины стека записано в регистре sp, причем при записи в стек значение этого смещения уменьшается, то есть стек растет вниз от максимально возможного адреса. Таким образом, стек расположен

«вверх ногами» [1, с. 22-23, п.2.1.3].

25

Один из полезных способов передачи параметров в подпрограмму

состоит в занесении

параметров в стек (см. уч. пос., ч.6). Стек находится в

сегменте, на который указывает регистр ss.

push bp

; сохранить содержимое регистра bp в стек

mov

bp,sp

; загрузка в ax первого параметра, передаваемого

mov

ax,[bp+4]

; при вызове подпрограммы на ассемблере.

4.16. Регистр sp

Регистр sp называется также указателем стека, он в каждый момент времени указывает на вершину стека. Вершина стека – это то место, в котором в стеке сохраняется помещаемое туда значение. Занесение значений в стек выполняется инструкцией push. Извлечение значений из стека выполняется инструкцией pop.

Рассмотрим, как изменяются регистры sp, ax и bp по мере выполнения следующего кода:

mov

ax,1

; ax:=1

push ax

; в стек заносится 1, и sp уменьшается на 2;

mov

bx,2

; bx := 2

push bx

; в стек заносится 2, и sp уменьшается на 2

pop

ax

; ax := 2, и sp увеличивается на 2

pop

bx

; bx := 1, и sp увеличивается на 2

Хотя процессор 8086 и позволяет записывать значения в sp или складывать и вычитать хранящиеся в регистре sp значения (как с регистрами общего назначения), лучше этого не делать!

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

4.17. Указатель инструкций (регистр ip)

Регистр ip всегда содержит смещение в памяти, по которому хранится следующая выполняемая инструкция.

cs

 

Сегмент кода

ip

 

 

 

 

 

 

 

Команда

 

 

 

 

 

 

 

Рис. 4.3

После выполнения инструкции указатель обычно перемещается на следующую за ней инструкцию, но некоторые инструкции (к ним

26

относятся вызовы процедур – call, переходы – jmp и jcc, циклы – loop, возврат из процедур – ret) могут привести к тому, что в ip будет загружено новое значение и выполнен переход на другой участок программы.

Значение регистра ip нельзя прочитать или записать непосредственно. Базовый адрес хранится в регистре cs, при этом указатель инструкций

задает смещение относительно этого базового адреса.

4.18. Сегментные регистры

Наиболее необычный аспект процессора 8086 – сегментация памяти. Предпосылкой сегментации является то, что процессор 8086 может адресоваться к 1 мегабайту памяти, а для этого необходимы 20-разрядные сегментные регистры.

Для формирования 20-разрядного адреса памяти процессор 8086 использует двухступенчатую схему адресации: каждый 16-разрядный указатель памяти или смещение комбинируется с содержимым соответствующего 16-разрядного сегментного регистра.

Для этого значение сегмента сдвигается влево на 4 (то есть умножается на 16), а затем складывается со смещением.

Рассмотрим, например, следующий фрагмент программы:

mov

ax,1000h

 

mov

ds,ax

; загрузка в ds значения 1000h

mov

si,201h

; загрузка в si значения 201h

mov

dl,[si]

 

Регистры ds и si можно представить в виде "сегмент:смещение" – 1000:201h. Адрес, из которого загружаются данные, представляет собой

((ds * 16) + si )

или

((1000h * 16) + 201h)

ds

 

 

Сегмент данных

 

si

 

 

 

 

 

 

 

 

 

 

 

Данные

 

 

 

 

 

 

 

 

 

Рис. 4.4

Программа получает доступ к полному адресному пространству в 1Мб только при использовании пары "сегмент:смещение".

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

27

Редко требуется загружать значение непосредственно в сегментный регистр (например, как это показано выше – значение 1000h). Чаще бывает нужно загружать в сегментные регистры имена сегментов, которые в ходе ассемблирования, компоновки и выполнения превращаются в числа.

Наиболее общим именем сегмента является @date, которое в упрощенных директивах определения сегментов используется для ссылки на используемый по умолчанию сегмент данных (см. уч. пос., ч.4).

Только блок памяти размером в 64 Кб может адресоваться через сегментный регистр, так как это максимальный объем памяти, к которой можно адресоваться с помощью 16-битового смещения. Это может оказаться неудобным при работе с большим (более 64 Кб) объемом памяти, так как и значение сегментного регистра, и смещение придется часто изменять.

Кроме того, единственная операция, которую можно выполнять с сегментными регистрами, состоит в копировании значений между сегментным регистром и каким-либо общим регистром или стеком (п. 4.72). Например, чтобы добавить значение 100 к регистру es, требуется следующее:

mov ax,es add ax,100 mov es,ax

Второй момент: каждая ячейка памяти адресуется через многие сочетания "сегмент:смещение". Например, адрес памяти 100h образуется с помощью следующих значений "сегмент:смещение": 0:100h, 1:f0h, 2:e0h и т.д., так как при вычислении всех этих пар "сегмент:смещение" получается значение адреса 100h.

Аналогично регистрам общего назначения каждый сегментный регистр играет свою, конкретную роль. Рассмотрим сегментные регистры более подробно.

4.19. Регистр cs

Регистр cs указывает сегмент кода, в котором находится следующая выполняемая инструкция. Она находится (рис. 4.5) по смещению, определяемому в сегменте кода регистром ip, на нее указывает адрес cs:ip.

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

cs

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

ip

Рис. 4.5

28

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

Никакие другие режимы адресации и никакие указатели памяти, отличные от ip, не могут нормально работать относительно регистра cs.

4.20. Регистр ds

Регистр ds указывает на начало сегмента данных, в котором находится большинство размещенных в памяти операндов. Обычно для ссылки на адреса памяти используются смещения, предполагающие использование регистров bx, si или di. Сегмент данных – это сегмент, в котором находится текущий набор данных.

ds

Сегмент данных

si

Данные

di

Данные

bx

Данные

Рис. 4.6

4.21. Регистр es

Регистр es указывает на начало блока памяти объемом 64 Кб, который называется дополнительным сегментом.

es

Дополнительный

сегмент данных

di

Данные

Рис. 4.7

Дополнительный сегмент доступен тогда, когда в нем возникает необходимость. Иногда он используется для выделения дополнительного

29

блока памяти объемом 64 Кб для данных. Однако доступ к памяти в дополнительном сегменте менее эффективен, чем доступ к памяти в сегменте данных.

Особенно полезен дополнительный сегмент, когда используются строковые инструкции. Все строковые инструкции, которые выполняют запись в память, используют (рис. 4.7) в качестве адреса памяти, в которую нужно выполнить запись, пару регистров es:di.

Это означает, что регистр es особенно полезен при копировании блоков, сравнении строк, просмотре памяти и очистке блоков памяти.

4.22. Регистр ss

Регистр ss указывает на начало сегмента стека, т.е. на блок памяти объемом до 64 Кб, в котором находится стек. Все инструкции, которые неявно используют регистр sp (включая занесение в стек, извлечение из стека, вызовы и возвраты управления), работают с сегментом стека, так как только регистр sp может использоваться для адресации памяти в сегменте стека.

Регистр bp также работает относительно сегмента стека. Это позволяет использовать регистр bp для доступа к параметрам и переменным, которые хранятся в стеке.

ss

 

 

 

Сегмент стека

 

 

 

 

 

 

sp

 

 

 

Данные

bp

Данные

Рис. 4.8

4.23.Директивы определения сегментов

Вассемблере предусмотрены два набора директив управления сегментами:

1) из упрощенных директив определения сегментов (делает управление сегментами относительно легким и идеально подходит для компоновки модулей ассемблера с языками высокого уровня, но поддерживает только некоторые из сегментных средств, имеющихся в ассемблере);

30

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]