ASM: Практична робота №3 до лекції №3
Практична робота № 3
Внутрішнє представлення цілочисельних даних в IBM PC
Мета роботи:
Отримати|здобуття| практичні навики|навиків| переведення чисел з десяткової системи числення в двійкову. Оволодіти навиками|навичками| представлення даних засобами мови Асемблер.
Порядок виконання роботи:
визначити для свого варіанту цілі числа;
перевести їх з десяткової в двійкову і шістнадцяткову систему числення;
отримати їх внутрішнє представлення;
написати програму опису цих даних на мові Асемблера і отримати лістинг;
перевірити правильність своїх викладень.
Цілочисельні дані мають бути представлені в усіх можливих для платформи Win32 форматах з урахуванням їх діапазону представлення.
У звіті по лабораторній роботі має бути представлений детальний протокол переведення усіх заданих чисел з 10-ої в 2-ву і 16-ву системи числення.
Варіанти
Базові числа: X =± 4567, Y =± 60.
До базових чисел ± X і ± Y, Ви повинні додати і відняти № свого варіанту.
Наприклад, X =± 4567, Y =± 60, № = 45.
Тоді вийдуть наступні вісім цілих чисел для варіанту № = 45, а саме:
-
1)
4567 +45 =
4612
2)
4567 -45 =
4522
3)
-4567 +45 =
-4522
4)
-4567 -45 =
-4612
5)
60 +45 =
105
6)
60 -45 =
15
7)
-60+45 =
-15
8)
-60 -45 =
-105
Контрольні запитання
Базові цілочисельні типи даних в IBM PC.
Діапазон допустимих значень для цілочисельних даних.
Теоритична частина.
Переведення цілого числа із десяткової системи числення в двійкову.
Спосіб 1.
Десяткове число необхідно ділити на 2 до отримання цілого залишку, меншого 2. Двійкове число можна представити у вигляді послідовності залишків ділення в порядку, зворотному їх отриманню. Старшу цифру числа дає останній залишок, а молодшу - перший.
Спосіб 2.
У двійковій системі число може бути представлено|уявляти| сумою ступенів двійки.
1610 - 24, отже
1610 =1*24 + 0*23 + 0*22 + 0*21 + 0*2°= 10000.
2410 = 16 + 8 = 1*24 + 1*23 + 0*22 + 0*21 + 0*2° = - 11000.
12510 = 64 + 32 + 16 + 8 + 4 + 1 = 1 * 26+ 1 * 25 + 1 * 24 + 1 * 23 + 1 * 22 + + 0*21+ 1 *2°= 1111101.
Внутрішнє представлення чисел.
Цілі числа у C/C++ можуть мати тип char або int, до яких можна додати специфікатори типу signed, unsigned, short, long. Усі ці типи даних мають визначену довжину комірки, а звідси і допустимий діапазон значень.
У Асемблері програміст сам вирішує, які дані (цілі або дійсні) він помістить в ту або іншу комірку. Наприклад, арифметичне дане, під яке відведене 32 або 64 біта, може бути як цілим, так і дійсним .
Цілі числа без знаку
Для платформи Win32, цілі числа без знаку можуть займати 8, 16 або 32 біта. Усі біти вважаються інформаційними.
Інформаційне поле числа |
||||||||||||||||||||||||||||||||
31 |
30 |
29 |
|
|
|
|
|
|
|
|
|
|
. |
. |
. |
|
|
|
|
|
|
|
|
|
|
|
4 |
3 |
2 |
1 |
0 |
|
|
біти |
|
||||||||||||||||||||||||||||||
старший |
молодший |
Приклад. У якому форматі його можна представити десяткове число 40 000? Тобто скільки йому потрібно біт і яке буде його внутрішнє (машинне) представлення?
Переведемо це число в двійкову систему, враховуючи те, що 212 = 4096, а 211 = 2048:
400010 = 211 + 210 + 29+ 28+ 27+ 25
4000-2048=1952 210 = 1024
1952-1024=928 29 = 512
928-512=416 28 = 256
416-256=160 27 = 128
160-128=32 25 = 32
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
Міімальна кількість біт для представлення числа 4000 – дванадцять. Розширемо число до 16 біт (2 байти), додаючи ліворуч нулі. Розділемо число на тетеради.
0000 1111 1010 0000
0 F 9 0
Можна це число розмістити і в 32-х бітах:
0000 0000 0000 0000 0000 1111 1010 0000
Це буде для C/C++ unsigned int, int, unsigned long.
Цілі знакові числа
Розглянемо число, що складається з 4 біт. Воно може находитися в 24 = 16 різних станах, і його можна поділити навпіл: 8 станів (включаючи 0) будуть "додатними", 8 - "від’ємними".
Щоб від’ємне число відразу можна було відрізнити від додатного, зробимо старший, четвертий, біт знаковим; нехай він дорівнюватиме нулю для додатних чисел і одиниці - для від’ємних.
У чотирьох бітах можуть уміщатися (разом з нулем) числа, представлені в таблиці:
0 1 2 3 4 5 6 7 |
0000 0001 0010 0011 0100 0101 0110 0111 |
Задача. Отримати від’ємне число з додатного.
Дано: число 1 ( двійкове представлення 0001).
Отримати двійкове представлення числа -1.
Розробка алгоритму.
1 + (-1) = 0.
Нуль можна отримати таким чином:
1111
+ 1
----
10000
Результат додавання - одиниця, але вже в п'ятому, неіснуючому для 4-бітових чисел розряді (вона відкидається).
Т. ч.
(0001 + х) + 1 = 0
110
Яке число необхідно додати до будь-якого числа, щоб отримати 1111? Відповідь - його інвертоване представлення (нулі замінюються одиницями, а одиниці нулями) отримаємо:
0001 + 1110=1111.
Т. ч. від’ємні числа будуть кодуватися так, як показано в таблиці.
-8 |
1000 |
-7 |
1001 |
-6 |
1010 |
-5 |
1011 |
-4 |
1100 |
-3 |
1101 |
-2 |
1110 |
-1 |
1111 |
У нас немає коду для число - 8 оскільки для нього не існує додатного числа. Скористаємося тим, що
0001 + 1000 = 10000
Тоді, щоб отримати двійковий код - 7 можна
16 - 7 = 10000 – 0111 = 10012 = 910.
Перевірка:
7 + (-7) = 0111 + 1001= 10000 = 1610.
Тоді
-8 = 16-8 = 8 = 1000
Отриманий код для від’ємних чисел називається додатковим, тому що від’ємне число виходить доповненням додатного до 16.
Доповнення до шістнадцяти справедливо тільки для 4-битов. Для чисел розміром 8- 16 - і 32-значения будуть іншими, але принцип збережеться.
Висновок. Для отримання від’ємного числа з додатного необхідно інвертувати його і додати 1.
Діапазон допустимих значень залежить від кількості розрядів, відведених для числа з урахуванням того, що один розряд відводиться під знак числа.
-
Тип
Діапазон значень
Ступені двійки
1 байт
-128...+ 127
-27...(27-1)
2 байта
-32 768...+32 767
-215...(215-l)
4 байта
-2 147 483 648... +2 147 483 647
-232...(232-1)
8 байт
-9 223 372 036 854 775 808...
+9 223 372 036 854 775 807
-263 … (263-1)
Формула в загальному вигляді:
від 2n-1 до 2n-1 -1
Старший біт двійкового чисел відводиться під знак (S біт – Signum):
S = 0 – для додатних чисел;
S = 1 - для від’ємних чисел.
Тому, діапазон допустимих значень для позитивних значень в два рази менше беззнакових.
S |
Інформаційне поле числа (0,1) |
|||||||||||||||||
32 |
. . . |
16 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Приклад 1. У один байт помістити знакове число 12710:
0111 1111b = 7Fh = 127d
Приклад 2. Скільки біт необхідно для представлення числа -1607 і яке буде його внутрішнє (машинне) представлення?
| -1607 | = 0110 0100 0111b.
Тобто нашому числу достатньо 12 біт. Але такого формату немає, тому беремо 16 біт, додаючи провідні нулі:
0000 0110 0100 011lb
Робимо інверсію нашого коду, отримуємо: 1111 1001 1011 1000b
До отриманого коду добавляємо 1: 1111 1001 1011 1001b
F 9 B 9
Приклад 3. Розмістити -1607 в 32 бітах.
Відповідь: FFFF F9B9h
Звертаємо увагу на провідні двійкові одиниці. Число обов'язково має бути в знаковому форматі (наприклад, int ).
Якщо воно інтерпретуватиметься як беззнакове", то
FFFF F9B9h - 4294965689d
Т. ч. : двійковий код може бути один і той же для різних чисел. Усе залежить від програміста, як він цей код тлумачитиме.
Приклад 4. Розмістити -1607 в 64 бітах?
Відповідь: FFFF FFFF FFFF F9B9h
Цілочисельні типи, їх діапазони значень і кількість потрібної для них пам'яті приведені в наступній таблиці:
Тип |
Діапазон значень |
Необхідна пам'ять |
unsigned char |
0 ... 255 |
1 byte |
char |
-128 ... 127 |
1 byte |
unsigned short int |
0 ... 65 535 |
2 bytes |
short int |
-32 768 ...32 767 |
2 bytes |
int (long int) |
-2 147 483 648 ...2 147 483 647 |
4 bytes |
Література. Кип Р. Ирвин. «Язык Ассемблера для процессоров INTEL». Стр. 50-63
Основні елементи мови|язика| асемблера
Текст програми на асемблері містить|утримує| інструкції і|та| директиви.
Інструкції виконуються процесором.
Директиви - це спеціальні командами, які виконує не процесор, а сама програма-асемблер (транслятор).
Наприклад, директиви для визначення змінних, опису сегментів.
Синтаксис директив залежить від версії асемблера і|та| ніяк не пов'язаний з системою команд процесорів Intel. Різні асемблери можуть генерувати ідентичний машинний код для системи команд процесорів Intel, але|та| вони можуть підтримувати абсолютно|цілком| різний набір директив.
Визначення даних
За допомогою оператора визначення даних в сегменті даних резервується область пам'яті відповідної довжини для розміщення значення змінної.
Визначення однобайтових змінних - директива BYTE|т.
Приклад.
Valuel BYTE 'A' |
Символьна константа |
value2 BYTE 0 |
Найменше беззнакове байтове значення
|
value3 BYTE 255 |
Найбільше беззнакове байтове значення
|
value6 BYTE ? |
Неініціалізована змінна |
Valuel, value2, value3, value6 - імена змінних - мітка, значення яке відповідає зміщенню цієї змінної відносно|щодо| початку|начала| сегменту, в якому вона розташована|схильна|.
Якщо змінна не ініціалізується конкретним значення, значення ініціалізатора дорівнює ?.
Приклад 1|зразок|. Визначити дві змінні, кожна з яких займає|посідає| один байт.
.data ; директива початку сегмента даних
valuel BYTE 10h ; h – hex – шістндцяткова система 10h=16d
value2 BYTE 20h
value1 розташована|схильна| в сегменті даних із|із| зміщенням|зсувом| 0, а value2 розташовуватиметься в цьому ж сегменті із|із| зміщенням|зсувом| 1.
-
Зміщення|зсув|
Значення
0000:
10h
0001:
20h
Застаріла директива :
vail DB 255 ; Беззнакове байтове значення
val2 DB - 128 ; Знакове байтове значення
Приклад 2|зразок|. Множинна|численна| ініціалізація - в одному операторові визначення даних використовується декілька ініціалізаторів
.data
list BYTE 10,20,30,40
Зміщення|зсув| |
Значення |
0000: |
10 |
0001: |
20 |
0002: |
30d |
0003: |
40 |
Мітка list відноситься тільки|лише| до першого байта даних і|та| їй відповідає зміщення 0. Значення 10 розташовується із|із| зміщенням 0 відносно|щодо| сегменту даних, значення 20 - із|із| зміщенням 1, 30 - 2 і|та| 4 0 – 3. Дані задані в десятковій системі числення.
Приклад 3. Використання у одному операторі визначення даних ініціалізаторів, заданих в різних системах числення :
listl BYTE 10, 32, 41h, 00100010b
list2 BYTE 0Ah, 20h, 'A ', 22h
Приклад 4.|зразок| Визначити масив байт, в який помістити символьний рядок
stroka BYTE "Добридень"!, 0
Кожен символ займає|посідає| один байт. Рядок закінчуються нульовим байтом.
Один довгий оператор можна розділити на 2 коротких за допомогою символу оберненої косої риски (\).
Приклад|зразок|:
stroka BYTE " Рядок 1"
и
stroka
\ BYTE " Рядок 1" ; продовження попереднього рядка
Приклад|зразок|. Створити змінну, що містить|утримує| значення байтів, що повторюються.
BYTE 20 DUP(0) ; 20 байтів, усі дорівнюють нулю
BYTE 20 DUP(?) ; 20 байтів, значення яких не визначене
BYTE 4 DUP("СТІК ") ; 20 байтів: "СТЕК СТЕК СТЕК СТЕК "
Оператором DUP зазвичай|звично| користуються при виділенні пам'яті під рядок символів або масив, які можуть бути ініціалізовані або ні.