Рубрики
Учебный курс

Учебный курс. Урок 8. Числа со знаком и без

Со школьной скамьи нас учили, что у чисел бывают отрицательные значения. Дело выглядело просто, записываешь число на бумаге, рисуешь черточку слева и все – положительное число превратилось в отрицательное. Для арифметической операции нужно от положительного числа отнять модуль отрицательного числа. К сожалению, такой подход совершенно не приемлем для машинных вычислений, потому что процессор не разделяет числа на положительные и отрицательные, а к числу нельзя просто пририсовать  черточку. Да и хранить её негде 🙂 Разве что «спрятать» в самом старшем бите.

В программировании на ассемблере числа без знака – любые числа, не имеющие знака минус в привычном представлении. То есть любые числа от нуля и выше. Для байта это означает любые числа от нуля до 255, для двух байт от 0 до 65535.

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

Казалось бы, для хранения чисел со знаком нужно просто отвести старший бит под знак и этого достаточно (прямое кодирование числа со знаком). Но в истории развития ЭВМ для цели хранения числа со знаком помимо прямого кода использовали обратный и дополнительный код. Именно дополнительный код наиболее распространен в наше время, также он входит в архитектуру процессоров x86.

Дополнительный код как способ хранения чисел со знаком

Рассмотрим число 7. В двоичном виде оно представлено как 00000111.Чтобы превратить его в отрицательное значение, понятное процессору x86, необходимо конвертировать его в дополнительный код. Для этого все биты инвертируются (1 меняются на 0, а 0 на 1), а к младшему биту прибавляется единица:

Преобразование числа 7 в дополнительный код

Процесс перевода отрицательных чисел в положительные одинаков.

Синтаксис FASM

Обозначать привычные нам десятичные числа в коде программы можно с использованием знака минус «-», например:

Однако не только десятичные числа конвертируются в отрицательные с прибавлением «минуса», также такой приём проходит с числами других систем счисления и со строчными символами:

Как было написано выше, процессор не делит числа не положительные и отрицательное. Поэтому эта роль программиста определять, какими числами он оперирует в своей программе. Ведь от того интерпретируется байт как число без знака или как число со знаком, зависит его значение. Например, число со знаком -7 соответствует число без знака 249:

Отличие числа без знака от числа со знаком

Диапазоны значений чисел со знаком и без

Числа без знака хранят в два раза большее положительные значения, чем это делают числа со знаком. Потому что числа со знаком также хранят отрицательные значения. Байт хранит 256 комбинаций из 8 бит, что соответствует 256 различным числам (включая 0). Граница верхнего хранимого числа в байте для числа без знака равна «255» (11111111b). Ну а для числа со знаком такой верхней границе соответствует число «127» (01111111b), а минимальному «-128» (10000000b). Схожим методом распределяется диапазон для переменных длинной в 2 байта и 4 байта.

В последующих уроках мы будем называть 16 битые переменные (2 байта) как слово, а 32 битые (4 байта) как двойное слово. Это общепринятые обозначения, которые относят нас к процессору Intel 8086 и его 16 битному такту, то есть к способности обработать 16 бит данных или одно слово (word) данных за такт. Следовательно, 32-битные переменные уже называются двойное слово (double word, dword). Ну а 32-битные процессоры просто унаследовали обозначения переменных от младшего брата. Отсюда же проистекают имена директив dw (Define Word) и dd (Define Dword). Ну а db – это Define Byte.

Для подкрепления урока приведу наглядную таблицу диапазонов чисел со знаком и без знака:

Размер
переменной
Число без знакаЧисло со знаком
minmaxminmax
байт00000000111111111000000001111111
0255-128127
слово00000000 0000000011111111 1111111110000000 0000000001111111 11111111
065 535-32 76832 767
двойное
слово
0000…00001111…11111000…00000111…1111
04 294 967 295-2 147 483 6482 147 483 647
и т.д.

Главный подводный камень любых операций с числами это выход за пределы хранимого в регистре или памяти диапазона. К примеру два больших положительных числа при сложении выйдут за свой диапазон и произведут отрицательное число! Из-за чего изменятся соответствующие флаги процессора, поведение и значение которых мы еще не раз рассмотрим в следующих уроках. Для избегания таких ситуаций программист должен оптимизировать операции с числами резервируя достаточное пространство под результат и т.д.

2 ответа к “Учебный курс. Урок 8. Числа со знаком и без”

Очень признателен за ваш труд, изучаю с первого урока, только первое знакомство с ассемблером еще 8 лет назад случилось. Но как бывает, без практики мозги особождают память) Так что теперь, можно сказать, заного изучаю ассемблер по вашим урокам. благо, материал подается легко. Еще когда учил раньше, не разобрался со знаковыми числами, или не старался особо, но когда нужно отладить программу там есть операторы перехода, учитывающие знак и не учитывающие, вот тогда требуется вникать в аргументы, есть там знак или его нету. Например, этот урок привел в порядок мозги, так что старые знания еще дают о себе знать)

Добавить комментарий