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

Методичка - Микропроцессоры микроЭВМ

.pdf
Скачиваний:
54
Добавлен:
02.05.2014
Размер:
551.11 Кб
Скачать

ЛАБОРАТОРНАЯ РАБОТА № 4

Работа со стеком

1. Цель работы

Исследование правил работы со стеком, изучение команд PUSH, POP, CALL, RET,

RST.

2. Задание на лабораторную работу

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

Перед выполнением программы сохранить все регистры микропроцессора в стеке и восстановить их после выполнения программы в исходное состояние.

3. Краткие сведения из теории

Стек – участок памяти в ОЗУ, выделенный программистом, в котором данные или адреса сохраняются и из которого извлекаются посредством стековых операций. Стековые операции выполняются командами PUSH, POP, CALL, RET, RST. Программист определяет, какой участок памяти выделяется под стек, с помощью специального 16-битового регистра, который называется стековым указателем (международное обозначение – SP, русское обозначение – УС). При работе со стеком выполняется следующее правило: «Первым вошел в стек, последним вышел из стека».

При работе со стеком различают две операции: запоминание данных из регистровой пары (PUSH) или счетчика команд (CALL, RST) в стеке и извлечение данных из стека в регистровую пару (POP) или в счетчик команд (RET).

Последовательность действий при запоминании данных в стеке:

1.Старшие 8 битов данных сохраняются в адресе памяти на 1 меньше, чем содержимое стекового указателя.

2.Младшие 8 битов данных сохраняются в адресе памяти на 2 меньше, чем содержимое стекового указателя.

3.Стековый указатель автоматически декрементируется (уменьшается) на 2. Последовательность действий при извлечении данных из стека:

1.Младшие 8 битов данных извлекаются из адреса памяти, соответствующей содержимому стекового указателя.

2.Старшие 8 битов данных извлекаются из адреса памяти, соответствующей содержимому стекового указателя + 1.

3.Стековый указатель автоматически инкрементируется на 2.

Часто группу команд в программе необходимо повторять много раз. Иногда в таких случаях лучше применять подпрограммы.

Подпрограмма кодируется подобно любой другой группе операторов языка, и к ней обращаются по имени, которое является меткой первой команды подпрограммы. Программист обращается к подпрограмме путем записи ее имени в поле операнда команды CALL. Когда выполняется CALL, адрес следующей команды после CALL вводится в стек и выполнение программы продолжается с первой команды подпрограммы. Когда подпрограмма завершила свою работу, выполняется команда RETURN, которая вызывает пересылку адреса из стека в счетчик команд, и выполнение программы продолжается с команды, следующей за CALL. Таким образом, одну копию подпрограммы можно вызывать из ряда точек без ее дублирования.

21

Подпрограмма (листинг 1) M1 инкрементирует 16-битовое число, сохраняемое в двух последовательных ячейках памяти, а затем возвращается к команде, которая следует за оператором CALL. Адрес инкрементируемого числа предварительно засылается в Н- и L- регистры.

Когда выполняется первый вызов, адрес 8204Н вводится в стек, а управление передается по адресу 8400Н. Выполнение любого оператора RET в теле подпрограммы M1 вызывает чтение адреса из стека в счетчик команд, выполнение продолжается с адреса 8204Н (поскольку оператор CALL имеет длину 3 байта).

Затем выполняется второй вызов, адрес 8306H вводится в стек, и управление снова передается M1. Теперь любая команда RETURN вызовет продолжение выполнения с ад-

реса 8306H.

Обратите внимание, что M1 в процессе могла бы вызвать другую подпрограмму, вызывая ввод в стек другого адреса. Ограничением является только размер памяти, доступной для стека.

Заметим, что любая подпрограмма может помещать данные в стек для временного хранения, что не повлияет на последовательность вызовов и возвратов, если только эти данные извлекаются из стека до выполнения команды RETURN.

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

Листинг 1. Пример использования подпрограммы

Адрес

Код

Мет-

Мнемоника

Примечание

 

 

 

ка

 

 

1

8200

E5

 

PUSH H

Запись в стек регистровой пары HL

2

8201

CD 06 82

 

CALL M1

Вызов подпрограммы по метке М1

3

8204

E1

 

POP H

Извлечение из стека регистровой пары

 

 

 

 

 

HL

4

8205

E7

 

RST32

Завершение программы

 

 

 

 

 

 

 

8300

21 00 81

 

LXI

 

 

 

 

 

H,8100H

 

 

8303

CD 06 82

 

CALL M1

Вызов подпрограммы по метке М1

 

8306

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

8400

34

M1:

INR M

M(HL)=M(HL)+1

5

8401

C0

 

RNZ

Условный возврат из подпрограммы

 

8402

23

 

INX H

HL=HL+1

 

8403

34

 

INR M

M(HL)=M(HL)+1

6

8404

C9

 

RET

Возврат из подпрограммы

22

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

Начальное значение стека обозначено буквами АААА (табл. 17). Стрелкой (→) обозначено положение указателя стека в каждой фазе выполнения программы. Звездочкой

(*) обозначено состояние стека после выполнения команды RST32.

Таблица 17. Состояние стека при разных фазах программы

AAAA -4

 

 

→04

→04

 

 

 

AAAA -3

 

 

82

82

 

 

 

AAAA -2

 

→L

L

L

→L

 

→06

AAAA -1

 

H

H

H

H

 

82

AAAA

 

 

 

 

 

УС

1

2

5

6

3

4

*

4. Задание к лабораторной работе

Составить, отладить и продемонстрировать программу в соответствии с вариантом. При написании программы учесть следующее:

Указатель стека проинициализирован в УОУ встроенным программным обеспечением и не требует задания.

Возврат из подпрограммы необходимо производить только при помощи команд группы RET. Переход из тела подпрограммы в тело основной программы при помощи команд группы JMP вызывает заполнение стека неиспользованными адресами возврата и в итоге нарушает работу программы.

5.Содержание отчета

Отчет должен содержать листинг программы и блок-схему программы.

6. Контрольные вопросы

6. 1. На что воздействуют биты условий?

6. 2. Как выполняется команда CALL (RST, PUSH, POP, RET).

23

ЛАБОРАТОРНАЯ РАБОТА № 5

Выполнение сложных арифметических действий

1. Цель работы

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

2. Задание на лабораторную работу

Разработать программу в соответствии с заданием (табл. 18)

Таблица 18. Задания к лабораторной работе № 5

 

 

1-й операнд

2-й операнд

Задание

Раз-

Система

Раз-

Система

ряд-

счисле-

ряднос

счисле-

 

 

 

 

ность

ния

ть

ния

1

Преобразовать

4

10

-

8

2

Преобразовать

4

8

-

10

3

Преобразовать

4

10

-

16

4

Преобразовать

4

16

-

10

5

Преобразовать

4

16

-

8

6

Преобразовать

4

8

-

16

7

Преобразовать

2

10

-

8

8

Преобразовать

2

8

-

10

9

Преобразовать

2

10

-

16

10

Преобразовать

2

16

-

10

11

Преобразовать

2

16

-

8

12

Преобразовать

2

8

-

16

13

Перемножить

4

10

4

10

14

Перемножить

4

8

4

8

15

Перемножить

4

16

4

16

16

Перемножить

4

10

4

8

17

Перемножить

4

10

4

16

18

Перемножить

4

16

4

8

19

Перемножить

2

10

4

10

20

Перемножить

2

8

4

8

21

Перемножить

2

16

4

16

22

Перемножить

2

10

4

8

23

Перемножить

2

10

4

16

24

Перемножить

2

16

4

8

25

Поделить

4

10

4

10

26

Поделить

4

8

4

8

27

Поделить

4

16

4

16

28

Поделить

4

10

4

8

29

Поделить

4

10

4

16

30

Поделить

4

16

4

10

31

Поделить

4

16

4

8

24

 

 

1-й операнд

2-й операнд

Задание

Раз-

Система

Раз-

Система

ряд-

счисле-

ряднос

счисле-

 

 

 

 

ность

ния

ть

ния

32

Поделить

4

8

4

10

33

Поделить

4

8

4

16

34

Поделить

2

10

4

10

35

Поделить

2

8

4

8

36

Поделить

2

16

4

16

37

Поделить

2

10

4

8

38

Поделить

2

10

4

16

39

Поделить

2

16

4

10

40

Поделить

2

16

4

8

41

Поделить

2

8

4

10

42

Поделить

2

8

4

16

43

Сложить

4

10

4

10

44

Сложить

4

8

4

8

45

Сложить

4

16

4

16

46

Сложить

4

10

4

8

47

Сложить

4

10

4

16

48

Сложить

4

16

4

8

49

Сложить

6

10

6

10

50

Сложить

6

8

6

8

51

Сложить

6

16

6

16

52

Сложить

6

10

6

8

53

Сложить

6

10

6

16

54

Сложить

6

16

6

8

55

Вычесть

4

10

4

10

56

Вычесть

4

8

4

8

57

Вычесть

4

16

4

16

58

Вычесть

4

10

4

8

59

Вычесть

4

10

4

16

50

Вычесть

4

16

4

10

61

Вычесть

4

16

4

8

62

Вычесть

4

8

4

10

63

Вычесть

4

8

4

16

64

Вычесть

2

10

4

10

65

Вычесть

2

8

4

8

66

Вычесть

2

16

4

16

67

Вычесть

2

10

4

8

68

Вычесть

2

10

4

16

69

Вычесть

2

16

4

10

70

Вычесть

2

16

4

8

71

Вычесть

2

8

4

10

72

Вычесть

2

8

4

16

25

3. Краткие сведения из теории

3. 1. Многобайтное сложение

Команды над битом переноса и команду ADC (сложение с переносом) можно использовать для сложения чисел произвольной длины без знака. Рассмотрим сложение двух 3-байтовых 16-ричных чисел (рис. 3).

 

32AF8AH

 

 

 

32H

 

 

 

 

 

AFH

 

 

 

 

 

8AH

 

+

 

 

 

 

 

+ 84H

 

 

 

 

+

 

 

 

 

 

 

 

 

 

+

 

 

 

 

84AA90H

 

 

 

 

 

 

AAH

 

 

 

 

 

 

 

 

 

 

90H

 

= B75A1AH

 

= B6H

 

 

 

 

 

=59H

 

 

 

 

 

 

 

 

 

+

 

 

 

 

+

 

 

 

 

 

=1AH

 

01H

 

 

 

01H

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

= B7H

 

 

 

 

=5AH

 

 

 

 

 

Перенос=1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Пернос=1

Рис. 3. Сложение многобайтного числа

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

1.В регистре находится длина каждого прибавляемого числа (в данном случае – 3).

2.Слагаемые хранятся в памяти, начиная с младших байтов, по адресам FIRST и SECND соответственно.

3.Результат будет накапливаться от байта младшего разряда до байта старшего разряда с началом в ячейке памяти FIRST, заменяя первоначальное содержимое этих ячеек.

Память до сложения

Память после сложения

FIRST

8A

 

 

 

 

 

 

 

 

 

 

 

1A

 

 

 

 

 

 

 

 

 

 

 

 

 

FIRST+1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

AF

 

 

 

 

 

 

 

 

 

 

 

5A

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

FIRST+2

32

 

 

 

 

 

 

 

 

 

 

 

B7

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SECND

90

 

 

 

 

 

 

 

 

 

 

 

90

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SECND+1

AA

 

 

 

 

 

 

 

 

 

 

 

AA

 

 

 

 

 

 

 

 

 

 

 

 

 

SECND+2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

84

 

 

 

 

 

 

 

 

 

 

 

84

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 4. Карта памяти при многобайтном сложении

3. 2. Многобайтное вычитание

Рассмотрим следующее вычитание двух двухбайтных 16-ричных чисел (табл. 19).

1301H0503H

=0DFEH

26

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

При вычитании младших байтов бит переноса (= 0) показывает отсутствие заема.

Таблица 19. Многобайтное вычитание

 

00000001=01H

 

 

 

 

11111101=- (03H +перенос)

 

 

Вычитание младших байтов

 

 

11111111=0FEH

 

 

 

 

 

Бит переноса =1, указывая наличие заема

 

00010011=13H

 

 

 

 

11110101=- (05H +перенос)

 

 

Вычитание старших байтов

 

 

00001101=0DH

 

 

 

 

 

Бит переноса сбрасывается

, указывая отсутствие заема

Всякий раз, когда имеет место заем, команда SBB инкрементирует вычитаемое на 1, что эквивалентно заему 1 из уменьшаемого. Для создания подпрограммы многобайтного вычитания необходимо продублировать подпрограмму много байтного сложения, заменяя команду ADC на команду SBB. Программа затем вычтет число, начинающееся в SECND, из числа, начинающегося в FIRST, помещая результат в FIRST.

3. 3. Десятичное сложение

Любую 4-битовую величину данных можно рассматривать как десятичную цифру 0…9, если не содержатся комбинации, соответствующие 16-ричным цифрам А…F. Для того чтобы сохранить эту десятичную интерпретацию при выполнении сложения, необходимо прибавлять 6 к 4-битовой величине всякий раз, когда сложение дает результат 10…15, т. к. каждая 4-битовая величина данных может содержать на шесть комбинаций больше, чем существует десятичных цифр.

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

Установка битов переноса и вспомогательного переноса также влияет на операцию DAA, что дает возможность складывать более чем двухзначные десятичные числа (табл. 20).

Таблица 20. Десятичное сложение

+2985D4936D

=7921D

Сброс бита переноса и прибавление двух младших цифр

+85H =10000101B

36H =00110110B

0BBH =10111011B

Перенос = 0 Вспомогательный перенос = 0

Выполнение команды DAA. Поскольку самые правые 4 бита >10D, то 6 будет прибавлено к аккумулятору

27

+ 0BBH =10111011B 6H =00000110B

0C1H =11000001B

Поскольку левые четыре бита теперь >10D, то 6 будет прибавлено к этим битам, устанавливая бит переноса

+ 0BBH =10111011B 60H =00110000B

21H =00100001B

Бит переноса = 1

Аккумулятор теперь содержит 21Н. Запоминаем эти две цифры

Складываем следующие две цифры

+ 29H =00101001B 49H =01001001B

73H =01110011B

Перенос = 0 Вспомогательный перенос = 1

Аккумулятор содержит 73Н

Выполнение команды DAA. Поскольку бит вспомогательного переноса установлен, то 6 будет прибавлено к аккумулятору

+ 73H =01110011B 6H =00000110B

79H =01111001B

Бит переноса =0

Поскольку самые левые 4 бита <10D, а бит переноса сброшен, то никаких дальнейших действий не происходит

Правильный десятичный результат равен 7921D

Подпрограмма сложения десятичных чисел аналогична подпрограмме многобайтного сложения и может быть получена из нее путем введения команды DAA после команды ADC M. Каждая итерация программного цикла складывает по две десятичные цифры данных чисел.

3. 4. Десятичное вычитание

Любую 4-битовую величину данных можно рассматривать как десятичную цифру 0…9, если не содержатся комбинации, соответствующие 16-ричным цифрам А…F. Команда DAA (десятичная настройка аккумулятора) может применяться для того, чтобы выполнить вычитание одного байта (представляющего 2 десятичные цифры) из другого, создавая двузначный десятичный результат. С помощью DAA можно производить вычитание многозначных десятичных чисел. Процесс состоит из получения дополнения до 100 вычитаемого и прибавление результата к уменьшаемому. Например, для вычитания 34D из 56D дополнение до 100 34D (100D – 34D = 66D) прибавляется к 56D. Получаем 122D, что при усечении до 8 битов дает 22D – правильный результат. Если посредством предшествующего вычитания был создан заем, то для компенсации заема создается дополнение вычитаемого до 99 (табл. 21, 22).

 

Таблица 21. Десятичное вычитание

 

 

Шаг

Действие

1

Устанавливаем бит переноса в 1, что указывает на отсутствие заема

2

Загружаем в аккумулятор 99Н, соответствующее по представлению 99D

3

Прибавляем 0 к аккумулятору с переносом, получаем 99Н или 9АН, и бит

переноса сбрасывается

28

4

Вычитаем две цифры вычитаемого из аккумулятора, создавая дополнение

до 99 или до 100

5

Прибавляем две цифры уменьшаемого к аккумулятору

 

Используем команду DAA для проверки того, что результат в аккумуляторе

6

находится в десятичном формате и для индикации заема с помощью бита

 

переноса, если он имел место. Результат сохраняем

7

Если вычитание должно быть продолжено для следующих цифр, перейти к

 

шагу 2. В противном случае – останов

Таблица 22. Пример десятичного вычитания

4358D1362D

=2996D

Устанавливаем перенос = 1

Загружаем в аккумулятор 99Н

Прибавляем 0 с учетом бита переноса к аккумулятору

+99H =10011001B

+0H =00000000B

1H =00000001B

9AH =10011010B

Вычитаем цифры вычитаемого 62Н из аккумулятора

9AH =10011010B 62H = 01100010B

38H = 00111001B

Перенос = 1

Прибавляем цифры уменьшаемого 58Н к аккумулятору

+ 38H =00111000B 58H =01011000B

90H =10010000B

Перенос = 0 Вспомогательный перенос = 1

DAA преобразует аккумулятор в 96Н (поскольку вспомогательный перенос =1) и оставляет бит переноса равным 0, показывая, что имел место заем

Загружаем в аккумулятор 99Н. Прибавляем 0 с учетом бита переноса к аккумулятору. Аккумулятор равен 99Н

Вычитаем цифры вычитаемого 13Н из аккумулятора

99H =10011001B

13H = 00010011B

86H =10000110B

Перенос = 1

Прибавляем цифры уменьшаемого 43Н к аккумулятору

+ 86H =10000110B 43H =01000110B

C9H =11001001B

Перенос = 0 Вспомогательный перенос = 0

DAA преобразует аккумулятор в 29Н и устанавливает бит переноса =1, показывая, что заема не произошло

Результат вычитания 1362D из 4358D будет 2996D

29

3. 5. Программная реализация умножения и деления

Умножение двух 8-битовых чисел без знака может быть выполнено посредством одного из двух способов: повторное сложение или применение операции регистрового сдвига. Повторное сложение обеспечивает простейший, но самый медленный способ умножения. Например, произведение 2АН×74Н может быть получено путем прибавления 74Н к аккумулятору (предварительно обнуленному) 2АН раз. Используя операцию сдвига, мы получаем более быстрое умножение. Сдвиг байта влево на 1 бит эквивалентен умножению на 2, а сдвиг байта вправо на 1 бит эквивалентен делению на 2. Следующий процесс дает правильный двухбайтный результат умножения однобайтного множимого на однобайтный множитель.

 

 

 

 

Таблица 23. Умножение

 

 

 

 

 

 

 

 

 

 

Шаг

×

2AH =00101010B

 

Старший

Младший

а/б

 

 

 

 

 

байт резуль-

байт резуль-

 

3CH =00111100B

 

 

Действие

 

 

 

тата

тата

 

 

9D8H =100111011000B

0

 

Начало

 

0000 0000

0000 0000

1

а

Проверяем 0-й бит множителя; он равен 0

 

0000 0000

 

 

б

Сдвигаем 16-битовый результат вправо на 1

 

0000 0000

 

 

бит

 

 

 

2

а

Проверяем 1-й бит множителя; он равен 0

 

0000 0000

 

 

б

Сдвигаем 16-битовый результат вправо на 1

 

0000 0000

 

 

бит

 

0010 1010

 

3

а

Проверяем 2-й бит множителя; он равен 1.

 

0000 0000

 

 

Прибавляем 2АН к старшему байту резуль-

 

 

 

 

 

тата

 

0001 0101

 

 

б

Сдвигаем 16-битовый результат вправо на 1

 

0000 0000

 

 

бит

 

0011 1111

 

4

а

Проверяем 3-й бит множителя; он равен 1.

 

0000 0000

 

 

Прибавляем 2АН к старшему байту резуль-

 

 

 

 

 

тата

 

0001 1111

 

 

б

Сдвигаем 16-битовый результат вправо на 1

 

1000 0000

 

 

бит

 

0100 1001

 

5

а

Проверяем 4-й бит множителя; он равен 1.

 

1000 0000

 

 

Прибавляем 2АН к старшему байту резуль-

 

 

 

 

 

тата

 

0010 0100

 

 

б

Сдвигаем 16-битовый результат вправо на 1

 

1100 0000

 

 

бит

 

0100 1110

 

6

а

Проверяем 5-й бит множителя; он равен 1.

 

1100 0000

 

 

Прибавляем 2АН к старшему байту резуль-

 

 

 

 

 

тата

 

0010 0111

 

 

б

Сдвигаем 16-битовый результат вправо на 1

 

0110 0000

 

 

бит

 

 

 

7

а

Проверяем 6-й бит множителя; он равен 0

 

0001 0011

 

 

б

Сдвигаем 16-битовый результат вправо на 1

 

1011 0000

 

 

бит

 

 

 

8

а

Проверяем 7-й бит множителя; он равен 0

 

0000 1001

 

 

б

Сдвигаем 16-битовый результат вправо на 1

 

1101 1000

 

 

бит

 

 

 

1.Проверка самого младшего бита множителя. Если 0, то переход к следующему шагу. Если 1, то прибавить множимое к старшему байту результата.

2.Сдвиг всего двухбайтного результата вправо на один бит.

30