- •Содержание
- •Преобразование чисел
- •Целые числа
- •Дробные числа
- •Содержание отчета
- •Контрольные вопросы
- •Задание на занятие
- •Лабораторная работа №2
- •Объединение со структурой с битовыми полями в языке Си.
- •Содержание отчета
- •Контрольные вопросы
- •Задание на занятие
- •Лабораторная работа №3
- •Содержание отчета
- •Контрольные вопросы
- •Задание на занятие
- •Лабораторная работа №4
- •Содержание отчета
- •Контрольные вопросы
- •Задание на занятие
- •Лабораторная работа №5
- •Содержание отчета
- •Контрольные вопросы
- •Задание на занятие
- •Лабораторная работа №6
- •Программирование на ассемблере
- •Основные команды ассемблера
- •Директивы
- •Программные прерывания
- •Отладка программ
- •Содержание отчета
- •Контрольные вопросы
- •Задание на занятие
- •Лабораторная работа №7
- •Команда jmp
- •Команда Loop
- •Флаговый регистр (flags)
- •Команды условного перехода
- •Знаковые и беззнаковые данные
- •Команды логических операций: and, or, xor, test, not
- •Команды сдвига и циклического сдвига
- •Команды сдвига
- •Команды циклического сдвига
- •Содержание отчета
- •Контрольные вопросы
- •Задание на занятие
- •Литература
Содержание отчета
Для защиты лабораторной работы каждым студентом должен быть написан отчет о лабораторной работе, оформленный в отдельной тетради для лабораторных работ по курсу «Вычислительные машины, системы и сети», включающий тему, цель работы и содержащий следующие пункты:
Общие сведения о системах счисления.
Задание на занятие.
Алгоритм работы программы (блок-схема или словесное описание).
Листинг программы (смысловая часть).
Ответ на контрольный вопрос.
Контрольные вопросы
Что такое позиционная система счисления?
Как можно записать общую формулу для представления чисел в двоичной системе счисления?
Запишите общую формулу для представления чисел шестнадцатеричной системы счисления.
Как переводить целое десятичное число в двоичную систему счисления?
Как переводить целое шестнадцатеричное число в двоичную систему счисления?
Правило перевода целого десятичного числа в шестнадцатеричную систему счисления.
Как преобразовать двоичные и шестнадцатеричные дробные числа в десятичный вид?
Чем ограничивается длина дробной части числа при переводе из десятичной системы в двоичную?
Как связана длина дробной части десятичного числа и дробная часть шестнадцатеричного числа?
Задание на занятие
Запрограммировать один из способов преобразования вида чисел, написав программу на языке высокого уровня (Паскаль, Си).
Требования к программированию:
При написании программы нельзя использовать встроенные строки форматирования и стандартные процедуры преобразования вида чисел (itoa( ),pow(), (%x) и пр.)
Для ввода и вывода чисел можно использовать строковые переменные.
Длины целой и дробной частей в десятичном виде можно ограничить тремя знаками для каждой части.
Способ преобразования вида чиселдля программирования производится по следующим вариантам:
двоичное число в шестнадцатеричное (целая и дробная часть)
шестнадцатеричное число в двоичное (целая и дробная часть)
целое десятичное число в двоичное (2йспособ)
целое двоичное число в десятичное (2йспособ)
целое десятичное число в шестнадцатеричное
дробное десятичное число в дробное двоичное (без целой части)
дробное двоичное число в дробное десятичное (1йспособ, без целой части)
дробное двоичное число в дробное десятичное (2йспособ, без целой части)
Лабораторная работа №2
Побитовые операции
Продолжительность: 4 часа.
Цель: Изучение приемов установки, сброса и маскирования битов числа.
Основные сведения
Внутри компьютера числа, как и все остальные данные и команды, хранятся в двоичном виде. Минимальной единицей информации в компьютере является бит. Любой из битов может бытьустановлен (включен, то есть равен единице) илисброшен (выключен, то есть равен нулю).
Каждые восемь бит образуют байт. Одним байтом можно представить 28=256 различных значений от 000000002до 111111112. Несколько байт образуютслово, которое по длине обычно соответствует разрядности регистра данных процессора. Мы будет рассматривать 16-ти разрядные слова.
Группы бит. Отдельные биты внутри байта или слова могут нести определённую информацию. Например, информация в байте, отвечающем за цветовой атрибут текста, распределена следующим образом:
-
7
6
5
4
3
2
1
0
B
b
b
b
f
f
f
f
ffff = 4-битный цвет символов (от 0 до 0xF)
bbb = 3-битный цвет фона (от 0 до 7)
B = бит мерцания (или бит интенсивности)
Наборы битов ffff,bbbиBназываютсяполями.
Поля цвета имеют побитовое смысловое значение: RGB, то есть младший бит отвечает за синий (Blue) цвет, средний бит – зеленый (Green) а старший бит – красный (Red). Наличие установленных битов в разных цветахRGBдаёт соответствующую смесь цветов [2]. Для четырёхбитного поляffffсамый старший бит отвечает за интенсивность цвета (см. Табл. 2.1.)
Таблица 2.1. Коды цветов.
Инт./ мерц. |
R |
G |
B |
Значение байта цвета |
Цвет (интенсивный/мигающий) |
0 |
0 |
0 |
0 |
0 |
Черный |
0 |
0 |
0 |
1 |
1 |
Синий |
0 |
0 |
1 |
0 |
2 |
Зеленый |
0 |
0 |
1 |
1 |
3 |
Бирюзовый |
0 |
1 |
0 |
0 |
4 |
Красный |
0 |
1 |
0 |
1 |
5 |
Малиновый |
0 |
1 |
1 |
0 |
6 |
Коричневый |
0 |
1 |
1 |
1 |
7 |
Светло-серый |
1 |
0 |
0 |
0 |
8 |
Темно-серый /Черный |
1 |
0 |
0 |
1 |
9 |
Ярко-синий /Синий |
1 |
0 |
1 |
0 |
A |
Ярко-зеленый /Зеленый |
1 |
0 |
1 |
1 |
B |
Ярко-бирюзовый /Бирюзовый |
1 |
1 |
0 |
0 |
C |
Ярко-красный /Красный |
1 |
1 |
0 |
1 |
D |
Ярко-малиновый /Малиновый |
1 |
1 |
1 |
0 |
E |
Желтый /Коричневый |
1 |
1 |
1 |
1 |
F |
Белый /Светло-серый |
В языке Си для изменения цветового атрибута текста служит стандартная функция textattr(CONIO.h):void textattr(int newattr).
Следует отметить, что стандартные функции вывода на стандартное устройство не реагируют на изменение атрибута цвета [3]. Для вывода цветного текста следует использовать стандартные функциивывода в текстовое окно, например,cprintf(CONIO.h).
Пример 2.1 На синем фоне жёлтыми буквами вывести фразу "Hello, world!".
#include <conio.h>
#include <stdio.h>
void main()
{ clrscr(); //очистка экрана
textattr(0x1E); //установка цветов фона и символов
printf("Это печать стандартного устройства");
printf("\nА это печать в текстовое окно:");
cprintf("\n\rHello, world!");
getch(); //ожидание нажатия клавиши
}
Функция cprintf()в отличие отprintf()выводит управляющую комбинацию\n(перевод строки) просто как перевод строки. Для привычного начала новой строки в функцииcprintf()следует дополнительно применять еще одну управляющую комбинацию\r (возврат каретки).
Команда textattr(0x1E)устанавливает цвет символов – жёлтый на синем фоне. В данной команде мы использовали шестнадцатеричное представление чисел с той целью, чтобы было легче определить цвет фона и цвет символа. Но результат выполнения команды не изменится, если мы будем использовать десятичные числа:textattr(30).
Для того чтобы задать цвет символа и фона с помощью переменных, можно использовать операцию побитового сдвига влево на четыре бита (пример 2.2), что соответствует умножению на . Таким способом переменнаяпомещается в поле цвета символов, а переменнаяв поле цвета фона.
Пример 2.2 Задать цвет фона и символа с клавиатуры и вывести фразу "Hello, world!" на языке Си.
#include <conio.h>
#include <stdio.h>
int i,j;
void main()
{ clrscr(); //очистка экрана
printf("Введите цвет фона: ");
scanf("%d",&i); //чтение цвета фона
printf("Введите цвет символов: ");
scanf("%d",&j); //чтение цвета символов
textattr(j+(i<<4)); //установка цветовых атрибутов
cprintf("\n\rHello, world!"); //вывод фразы на экран
getch(); //ожидание нажатия клавиши
}
Чтобы задать ярко-синий фон для выводимого текста, недостаточно одной команды textattr(0x9E). По умолчанию эта команда даёт в результате мигающие жёлтые символы на синем фоне. Для переключениярежима интенсивность/мерцаниеиспользуется прерываниеBIOS10h, функция 10h, подфункция 3. Если регистрbl=0, то включаетсярежим интенсивного цвета фона:
asm { mov ax, 1003h
mov bl, 0
int 10h}
В случае bl=1 – включаетсярежим мерцания символов:
asm { mov ax, 1003h
mov bl, 1
int 10h}
Приведенные строки следует включать в текст основной программы, учитывая, что одновременно на экране может отображаться только один из двух режимов: либо режим интенсивного цвета фона, либо режим мерцания символов.
Более подробно рассматривать вызов прерываний и регистры процессора мы будем на лабораторном занятии №6.
Изменение группы бит.При работе с байтами могут возникать ситуации, при которых необходимо определять или задавать значения одного или нескольких бит без изменения других бит.
Операция, при которой изменяется только часть байта, а остальные биты остаются неизменными, называется маскированием.Установкой бита называется присваивание ему значения единица.Сбросом бита называется присваивание ему значения нуль.Инвертирование бита означает изменение его значения на противоположное (в двоичной системе счисления значения 0 и 1 являются противоположными).
Маской называется байт, в котором установлены биты, соответствующие битам измененяемого байта. Если значения всех битов в маске инвертированы, то маска называетсяинвертированной.
Для изменения битов в байтах с помощью масок существует набор побитовых операций, представленный в таблице 2.2.
Таблица 2.2. Описание побитовых операторов.
Оператор языка Си |
Описание операторов |
& |
и |
^ |
исключающее или |
| |
или |
~ |
не (отрицание) |
>> k |
побитовый сдвиг на k бит вправо |
<< k |
побитовый сдвиг на k бит влево |
Таблица 2.3. Значения побитовых операторов.
Аргументы |
Значения функций | ||||
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
0 |
Для установкибитов в байте (или слове) применяется следующая последовательность действий:
Создаётся маска на изменяемые биты.
Маска накладывается на байт (слово) с помощью операции "или".
В последующих примерах мы будем производить операции над неким числом а, которое может быть определено в программе так: unsignedchara(целое беззнаковое число, длиной 1 байт, см. табл. 1.4). Это означает, что мы будем изменять биты числа только с нулевого по седьмой.
Пример 2.3 Установить седьмой бит в числе а.
Для установки седьмого бита используем выражение a |= 0x80 (тоже самое, что a = a | 0x80). В таблице 3.4 показано формирование маски и накладывание на исходный байт с помощью оператора | "или".
Таблица 2.4. Установка седьмого бита
Номера разрядов |
Основание | |
2 |
16 | |
7 6 5 4 3 2 1 0 |
1 0 | |
Пример исходного байта (a) |
0 0 1 1 0 0 1 0 |
3 2 |
Маска |
1 0 0 0 0 0 0 0 |
8 0 |
Результат операции "или" |
1 0 1 1 0 0 1 0 |
B 2 |
Чтобы установить группу битв байте (или слове), необходимо сложить маски для изменяемых бит или определить одну общую маску на все изменяемые биты, а затем накладывается на искомый байт (слово) с помощью операции "или".
Пример 2.4 Установка седьмого, четвёртого и третьего бита в числе а.
Для изменения указанных битов используем выражение a |= 0x98 (a = a | 0x98). Как формируется маска, можно посмотреть в таблице 2.5.
Таблица 2.5. Установка группы бит.
Номера разрядов |
Основание | |
2 |
16 | |
7 6 5 4 3 2 1 0 |
1 0 | |
Исходный байт (a) |
0 0 1 1 0 0 1 0 |
3 2 |
Маска на седьмой бит |
1 0 0 0 0 0 0 0 |
8 0 |
Маска на четвёртый бит |
0 0 0 1 0 0 0 0 |
1 0 |
Маска на третий бит |
0 0 0 0 1 0 0 0 |
0 8 |
Сумма масок или общая маска на 7, 4 и 3 |
1 0 0 1 1 0 0 0 |
9 8 |
Результат операции "или" |
1 0 1 1 1 0 1 0 |
DA |
Для сбросабитов в байте (или слове) применяется следующая последовательность действий:
Создаётся маска на изменяемые биты.
Маска инвертируется.
Инвертированная маска накладывается на байт (слово) с помощью команды "и".
Пример 2.5 Сброс седьмого бита в числе а.
Для сброса седьмого бита используем выражение a &= ~0x80. Как формируется маска и результат операции можно посмотреть в таблице 2.6.
Таблица 2.6. Сброс седьмого бита.
Номера разрядов |
Основание | |
2 |
16 | |
7 6 5 4 3 2 1 0 |
1 0 | |
Исходный байт (a) |
1 0 1 1 0 0 1 0 |
B 2 |
Маска |
1 0 0 0 0 0 0 0 |
8 0 |
Инвертированная маска |
0 1 1 1 1 1 1 1 |
7 F |
Результат операции "и" |
0 0 1 1 0 0 1 0 |
3 2 |
Чтобы сбросить группу битв байте (или слове), необходимо сложить маски для изменяемых бит или определить одну общую маску на изменяемые биты, затем общая маска инвертируется и накладывается на искомый байт (слово) с помощью операции "и".
Пример 2.6 Сброс седьмого, шестого и первого бита в числе а.
Для изменения указанных битов используем выражение a &= ~ 0x3D. Как формируются маски и результат операции можно посмотреть в таблице 2.7.
Таблица 2.7. Сброс группы бит.
Номера разрядов |
Основание | |
2 |
16 | |
7 6 5 4 3 2 1 0 |
1 0 | |
Исходный байт (a) |
0 0 1 1 0 0 1 0 |
3 2 |
Маска на седьмой бит |
1 0 0 0 0 0 0 0 |
8 0 |
Маска на шестой бит |
0 1 0 0 0 0 0 0 |
4 0 |
Маска на первый бит |
0 0 0 0 0 0 1 0 |
0 2 |
Сумма масок или общая маска на 7, 6 и 1 |
1 1 0 0 0 0 1 0 |
С 2 |
Инвертированная общая маска |
0 0 1 1 1 1 0 1 |
3 D |
Результат операции "и" |
0 0 1 1 0 0 0 0 |
3 0 |
Для инвертированиябитов в байте (или слове) применяется следующая последовательность действий:
Создаётся маска на инвертируемые биты.
Маска накладывается на байт (слово) с помощью команды "исключающее или".
Пример 2.7 Инвертирование шестого и седьмого бита в числе а.
Для инвертирования указанных битов используем выражение a ^= 0xC0. Как формируются маски и результат операции можно посмотреть в таблице 2.8.
Таблица 2.8. Инвертирование группы бит:
Номера разрядов |
Основание | |
2 |
16 | |
7 6 5 4 3 2 1 0 |
1 0 | |
Исходный байт (a) |
1 0 1 1 0 0 1 0 |
B 2 |
Маска |
1 1 0 0 0 0 0 0 |
C 0 |
Результат операции "искл. или" |
0 1 1 1 0 0 1 0 |
7 2 |
Определение одного или группы бит. Для того чтобы считать один или группу бит из байта (слова), необходимо сбросить ненужные разряды и выделенную группу бит сдвинуть вправо до нулевого разряда.
Пример 2.8 Определение значения пятого бита числа а.
Для определения значения указанных битов используем выражение bit5 = (a & 0x20) >> 5. Как формируется маска и результат операции можно посмотреть в таблице 2.9.
Таблица 2.9. Определение значения пятого бита.
Номера разрядов |
Основание | |
2 |
16 | |
7 6 5 4 3 2 1 0 |
1 0 | |
Исходный байт (a) |
1 0 1 1 0 0 1 0 |
B 2 |
Маска |
0 0 1 0 0 0 0 0 |
2 0 |
Результат операции "и" |
0 0 1 0 0 0 0 0 |
2 0 |
Результат операции >> 5 |
0 0 0 0 0 0 0 1 |
0 1 |
Обратите внимание на то, что значение переменной bit5 (unsigned char bit5) всегда будет, в зависимости от значения переменной a, либо нулем, либо единицей.
Для получения значений трёх разрядов подряд, например, 5, 4 и 3 бит, можно совершать аналогичные операции. Но результатом может оказаться значение от 0 до 7, что опять потребует расшифровки по разрядам. Поэтому желательно значения в группе бит определять поразрядно: для пятого, четвёртого и третьего бита отдельно, а результат сохранять не в отдельных переменных, а в массиве bit (unsignedcharbit[8]):
Пример 2.9 Определение пятого бита числа а.
bit[5] = (a&0x20)>>5, или bit[5] = (a>>5)&1
Пример 2.10 Определение четвёртого бита числа а.
bit[4] = (a&0x10)>>4, или bit[4] = (a>>4)&1
Пример 2.11Определение третьего бита числа а.
bit[3] = (a&8)>>3, или bit[3] = (a>>3)&1
Пример 2.12Определение k-того бита числа а в общем виде.
bit[k] = (a&(1<<k))>>k, или bit[k] = (a>>k)&1
На самом деле, если требуется только выводить на экран значения бит, то новые имена переменных массивов для хранения значений бит можно и вовсе не заводить:
Пример 2.13Вывод восьми бит числа а.
for (int i=7; i <=0; i--) printf( a>>i & 1)