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




Лабораторная работа №1

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

 

Цель работы

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

 

Сведения из теории

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

Биты и байты

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

Группа из девяти битов представляет собой байт; восемь битов которого содержат данные и один бит — контроль на четность. Восемь битов обеспечивают основу для двоичной арифметики и для представления символов, таких как буква A или символ *. Восемь битов дают 256 различных комбинаций включенных и выключенных состояний: от «все выключены» (00000000) до «все включены» (11111111). Например, сочетание включенных и выключенных битов для представления буквы A выглядит как 01000001, а для cимвола * — 00101010 (это можно не запоминать). Каждый байт в памяти компьютера имеет уникальный адрес, начиная с нуля.

 

Требование контроля на четность заключается в том, что количество включенных битов в байте всегда должно быть не четно. Контрольный бит для буквы A будет иметь значение единица, а для символа * — ноль. Когда команда обращается к байту в памяти, компьютер проверяет этот байт. В случае, если число включенных битов является четным, система выдает сообщение об ошибке. Ошибка четности может явиться результатом сбоя оборудования или случайным явлением, в любом случае, это бывает крайне редко.

Откуда компьютер «знает», что значения бит 01000001 представляют букву A? Когда на клавиатуре нажата клавиша A, система принимает сигнал от этой конкретной клавиши в байт памяти. Этот сигнал устанавливает биты в значения 01000001. Можно переслать этот байт в памяти и, если передать его на экран или принтер, то будет сгенерирована буква A.

По соглашению биты в байте пронумерованы от 0 до 7 справа налево:

Номера бит: 7 6 5 4 3 2 1 0

Значения бит: 0 1 0 0 0 0 0 1

Число 2 в десятой степени равно 1024, что составляет один килобайт и обозначается буквой К. Например, компьютер с памятью в 512 К содержит 512 х 1024, то есть, 524288 байт. Процессор в PC и в совместимых моделях использует 16-битовую архитектуру, поэтому он имеет доступ к 16-битовым значениям как в памяти, так и в регистрах. 16-битовое (двухбайтовое) поле называется словом. Биты в слове пронумерованы от 0 до 15 справа налево.

ASCII

Для целей стандартизации в микрокомпьютерах используется aмериканский национальный стандартный код для обмена информацией ASCII (American National Standard Code for Information Interchange). Читается как «аски» код. Именно по этой причине комбинация бит 01000001 обозначает букву A.

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

Двоичные числа

Так как компьютер может различить только нулевое и единичное состояние бита, то он работает в системе исчисления с базой 2 или в двоичной системе. Фактически бит унаследовал cвое название от английского «Binary digit» (двоичная цифра).

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

Самый правый бит имеет весовое значение 1, следующая цифра влево — 2, следующая — 4 и так далее. Общая сумма для восьми единичных битов в данном случае составит 1+2+4+...+128, или 255 (28 – 1).

Для двоичного числа 01000001 единичные биты представляют значения 1 и 64, то есть, 65. Но 01000001 представляет также букву A! Действительно, здесь момент, который необходимо четко уяснить. Биты 01000001 могут представлять как число 65, так и букву A:

- если программа определяет элемент данных для арифметических целей, то 01000001 представляет двоичное число эквивалентное десятичному числу 65;

- если программа определяет элемент данных (один или более смежных байт), имея в виду описательный характер, как, например, заголовок, тогда 01000001 представляет собой букву или «строку».

При программировании это различие становится понятным, так как назначение каждого элемента данных определено.

Двоичное число не ограничено только восемью битами. Процессор может использовать 16-битовую архитектуру, в этом случае он автоматически оперирует с 16-битовыми числами. 2 в степени 16 минус 1 дает значение 65535, а немного творческого программирования позволит обрабатывать числа до 32 бит (2 в степени 32 минус 1 равно 4294967295) и даже больше.

Двоичная арифметика

Компьютер выполняет арифметические действия только в двоичном формате. Поэтому программист на языке Ассемблера должен быть знаком с двоичным форматом и двоичным сложением:

0 + 0 = 0

1 + 0 = 1

1 + 1 = 10

1 + 1 + 1 = 11

Отрицательные числа

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

Рассмотрим пример:

Число 65: 01000001

Инверсия: 10111110

Плюс 1: 10111111 (равно -65).

В случае, если прибавить единичные значения к числу 10111111, 65 не получится.

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

Двоичное значение: 10111111

Инверсия: 01000000

Плюс 1: 01000001 (равно +65).

Сумма +65 и -65 должна составить ноль:

01000001 (+65) + 10111111 (-65) = (1) 00000000

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

Двоичное вычитание выполняется просто: инвертируется знак вычитаемого и складываются два числа. Вычтем, например, 42 из 65. Двоичное представление для 42 есть 00101010, и его двоичное дополнение: — 11010110:

65 01000001 +(-42) 11010110 = 23 (1) 00010111

Результат 23 является корректным. В рассмотренном примере произошел перенос в знаковый разряд и из разрядной сетки.

Можно видеть также, каким образом двоичными числами представлены уменьшающиеся числа:

+3 00000011

+2 00000010

+1 00000001

0 00000000

-1 11111111

-2 11111110

-3 11111101

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

 

Шестнадцатеричное представление

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

Двоичное: 0101 1001 0011 0101 1011 1001 1100 1110

Десятичное: 5 9 3 5 11 9 12 14

Так как здесь для некоторых чисел требуется две цифры, расширим систему счисления так, чтобы 10=A, 11=B, 12=C, 13=D, 14=E, 15=F. Таким образом, получим более сокращенную форму, которая представляет содержимое вышеуказанных байт:

59 35 B9 CE

Такая система счисления включает «цифры» от 0 до F, и так как таких цифр 16, она называется шестнадцатеричным представлениeм.

Шестнадцатеричный формат нашел большое применение в языке Ассемблера. В листингах ассемблирования программ в шестнадцатеричном формате показаны все адреса, машинные коды команд и содержимое констант. Также для отладки при использовании программы DOS DEBUG адреса и содержимое байтов выдается в шестнадцатеричном формате.

В случае, если немного поработать с шестнадцатеричным форматом, то можно быстро привыкнуть к нему. Следует помнить, что после шестнадцатеричного числа F следует шестнадцатеричное 10, что равно десятичному числу 16.

Заметьте также, что шестнадцатеричное 20 эквивалентно десятичному 32, шестнадцатеричное 100 — десятичному 256 и шестнадцатеричное 100 — десятичному 4096.

Сегменты

 

Сегментом называется область, которая начинается на границе параграфа, то есть, по любому адресу, который делится на 16 без остатка. Хотя сегмент может располагаться в любом месте памяти и иметь размер до 64 Кбайт, он требует столько памяти, сколько необходимо для выполнения программы.

Сегмент кодов

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

Регистр сегмента кодов (CS) адресует данный сегмент.

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

Сегмент данных содержит определенные данные, константы и рабочие области, необходимые программе. Регистр сегмента данных (DS) адресует данный сегмент.

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

Стек содержит адреса возврата как для программы для возврата в операционную систему, так и для вызовов подпрограмм для возврата в главную программу. Регистр сегмента стека (SS) адресует данный сегмент.

Еще один сегментный регистр, регистр дополнительного сегмента (ES), предназначен для специального использования. Последовательность регистров и сегментов на практике может быть иной.

 

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

Внутри программы все адреса памяти относительны к началу cегмента. Такие адреса называются смещением от начала сегмента. Двухбайтовое смещение (16-бит) может быть в пределах от шест.0000 до шест.FFFF или от 0 до 65535. Для обращения к любому адресу в программе, компьютер складывает адрес в регистре сегмента и смещение. Например, первый байт в сегменте кодов имеет смещение 0, второй байт — 01 и так далее до смещения 65535.

В качестве примера адресации, допустим, что регистр сегмента данных содержит шест.045F и некоторая команда обращается к ячейке памяти внутри сегмента данных со смещением 0032. Несмотря на то, что регистр сегмента данных содержит 045F, он указывает на адрес 045F0, то есть, на границе параграфа. Действительный адрес памяти поэтому будет следующий:

Адрес в DS: 045F0

Смещение: 0032

Реальный адрес: 04622

Каким образом процессоры адресуют память в один миллион байт?

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

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

Поэтому адрес хранится в сегментном регистре как шест. nnnn, а компьютер полагает, что имеются еще четыре нулевых младших бита (одна шест. цифра), то есть, шест.nnnn0. Таким образом, шест.FFFF0 позволяет адресовать до 1048560 байт.

В случае, если вы сомневаетесь, то декодируйте каждое шест.F как двоичное 1111, учтите нулевые биты и сложите значения для единичных бит.

Дамп памяти

 

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

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

В дампе памяти для программы видны данные сегмента в двух представлениях: шестнадцатеричном и символьном.

Обратите внимание на то, как размещены в памяти байты, входящие в слово. Пусть это будет значение 21CD, расположенное по адресу DS:0050. Сначала следует байт со значением CDh, а затем со значением 21h. Как видите, в памяти действительно сначала расположен младший байт значения, а затем старший.

 

 

Постановка задачи

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

2. Применить разработанные функции для вычисления значения выражения в соответствии с индивидуальным заданием (A, B, C, D принадлежит диапазону [-32767; 32767]).

3. Вывести на экран значения A, B, C, D, X в десятичном и двоичном виде, а также обеспечить имитацию вывода на экран дампа памяти с хранящимися в последовательных ячейках значениями этих переменных. Значения относительного адреса (сегмента и смещения), где хранятся переменные, вводятся пользователем вручную с клавиатуры. Определить абсолютные адреса каждой переменной.

 

Варианты заданий

1. A + B – C

2. (A + B) – (C + D)

3. –A + B + C

4. (A – C) – (B + D)

5. A – B + C

6. A – (B + C + D)

7. A – B – C

8. (A – C) – (B – D)

9. C – B – A

10. (–A + B) + (C – D)

11. B – C – A

12. (A + B) + (–C – D)

13. (A – B) + (C – D)

14. –B + C – A

15. (C – B) + (D – A)

16. A – (B + C + D)

17. B – (A + B – D)

18. (D – B – A) + C

19. –C + (A – B – D)

20. –A – (B + C + D)



Поделиться:




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

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2021-12-05 Нарушение авторских прав и Нарушение персональных данных


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