Старший бит в байте

Чисто технически было бы очень сложно сделать компьютер, который бы «понимал» десятичные числа. А вот сделать компьютер, который понимает двоичные числа достаточно легко. Двоичное число оперирует только двумя цифрами – 0 и 1. Несложно сопоставить с этими цифрами два состояния – вЫключено и включено (или нет напряженияесть напряжение). Процессор – это микросхема с множеством выводов. Если принять, что отсутствие напряжения на выводе – это 0 (ноль), а наличие напряжения на выводе – это 1 (единица), то каждый вывод может работать с одной двоичной цифрой. Сейчас мы говорим о процессоре очень упрощённо, потому что мы изучаем не процессоры, а системы исчисления. Об устройстве процессора вы можете почитать здесь: Структура процессора.

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

Итак, процессор (и компьютер в целом) использует двоичную систему, которая оперирует всего двумя цифрами: 0 и 1. И поэтому основание двоичной системы равно 2. Аналогично, основание десятичной системы равно 10, так как там используются 10 цифр.

Каждая цифра в двоичном числе называется бит (или разряд). Четыре бита – это полубайт (или тетрада), 8 бит – байт, 16 бит – слово, 32 бита – двойное слово. Запомните эти термины, потому что в программировании они используются очень часто. Возможно, вам уже приходилось слышать фразы типа слово данных или байт данных. Теперь, я надеюсь, вы понимаете, что это такое.

Отсчёт битов в числе начинается с нуля и справа. То есть в двоичном числе самый младший бит (нулевой бит) является крайним справа. Слева находится старший бит. Например, в слове старший бит – это 15-й бит, а в байте – 7-й. В конец двоичного числа принято добавлять букву b. Таким образом вы (и ассемблер) будете знать, что это двоичное число. Например, А теперь попробуем понять, как формируется двоичное число.

Ноль, он и в Африке ноль. Здесь вопросов нет. Но что дальше. А дальше разряды двоичного числа заполняются по мере увеличения этого числа. Для примера рассмотрим тетраду. Тетрада (или полубайт) имеет 4 бита.

Двоичное Десятичное Пояснения
0000
0001 1 В младший бит устанавливается 1.
0010 2 В следующий бит (бит 1) устанавливается 1, предыдущий бит (бит 0) очищается.
0011 3 В младший бит устанавливается 1.
0100 4 В следующий бит (бит 2) устанавливается 1, младшие биты (бит 0 и 1) очищаются.
0101 5 В младший бит устанавливается 1.
0110 6 Продолжаем в том же духе.
0111 7 .
1000 8 .
1001 9 .
1010 10 .
1011 11 .
1100 12 .
1101 13 .
1110 14 .
1111 15 .

Итак, мы видим, что при формировании двоичных чисел разряды числа заполняются нулями и единицами в определённой последовательности:

Если младший равен нулю, то мы записываем туда единицу. Если в младшем бите единица, то мы переносим её в старший бит, а младший бит очищаем. Тот же принцип действует и в десятичной системе: Всего для тетрады у нас получилось 16 комбинаций. То есть в тетраду можно записать 16 чисел от 0 до 15. Байт – это уже 256 комбинаций и числа от 0 до 255. Ну и так далее. На рис. 2.2 показано наглядно представление двоичного числа (двойное слово).

Читайте также:  Что называется эффективным значением тока

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

В общем случае, для представления числа M, большего 255 (здесь 255 = 2 8 − 1 <displaystyle 255=2^<8>-1> — максимальное целое число, записываемое одним байтом), приходится использовать несколько байтов. При этом число M записывается в позиционной системе счисления по основанию 256:

M = ∑ i = 0 n A i ⋅ 256 i = A 0 ⋅ 256 0 + A 1 ⋅ 256 1 + A 2 ⋅ 256 2 + ⋯ + A n ⋅ 256 n . <displaystyle M=sum _^A_cdot 256^=A_<0>cdot 256^<0>+A_<1>cdot 256^<1>+A_<2>cdot 256^<2>+dots +A_cdot 256^.>

Набор целых чисел A 0 , … , A n <displaystyle A_<0>,dots ,A_> , каждое из которых лежит в интервале от 0 до 255, является последовательностью байтов, составляющих M. При этом A 0 <displaystyle A_<0>> называется младшим байтом, а A n <displaystyle A_> старшим байтом числа M.

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

Содержание

Варианты записи [ править | править код ]

Порядок от старшего к младшему [ править | править код ]

Порядок от старшего к младшему (англ. big-endian — большим концом): A n , … , A 0 <displaystyle A_,dots ,A_<0>> . Этот порядок соответствует привычному порядку записи арабских цифр, например, число сто двадцать три было бы записано при таком порядке как 123. В этом же порядке принято записывать байты в технической и учебной литературе, если другой порядок явно не обозначен.

Этот порядок является стандартным для протоколов TCP/IP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня, разработанных для использования поверх TCP/IP. Поэтому порядок байтов от старшего к младшему часто называют «сетевым порядком байтов» (англ. network byte order ). Этот порядок байтов используется процессорами IBM 360/370/390, SPARC, Motorola 68000 (отсюда третье название — порядок байтов Motorola, англ. Motorola byte order ).

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

Порядок байтов от старшего к младшему применяется также во многих форматах файлов — например, PNG, FLV, EBML, JPEG.

Порядок от младшего к старшему [ править | править код ]

Порядок от младшего к старшему (англ. little-endian — малым концом): A 0 , … , A n <displaystyle A_<0>,dots ,A_>

Это обратный порядок по отношению к привычному порядку записи арабских цифр, например, число сто двадцать три было бы записано при таком порядке как 321.

Этот порядок записи принят в памяти персональных компьютеров с процессорами архитектуры x86, в связи с чем иногда его называют интеловский порядок байтов (по названию компании-создателя архитектуры x86). Современные процессоры x86 позволяют работать с одно-, двух-, четырёх- и восьмибайтовыми операндами. При таком порядке байтов очень удобно то обстоятельство, что при увеличении размера (количества байт) операнда, значение его первого байта остаётся прежним: 3210 → 3210’0000. При порядке от старшего к младшему значение изменилось бы, например: 0123 → 0000’0123;

Кроме x86, такой порядок байтов применяется в архитектурах VAX (отсюда ещё одно название англ. VAX byte order [1] ), DEC Alpha и многих других.

Также порядок от младшего к старшему применяется в USB, PCI, таблице разделов GUID, он рекомендован FidoNet. Но в целом соглашение little-endian поддерживают меньше кросс-платформенных протоколов и форматов данных, чем big-endian.

Переключаемый порядок [ править | править код ]

Многие процессоры могут работать и в порядке от младшего к старшему, и в обратном, например, ARM (по умолчанию — little endian), PowerPC (но не PowerPC 970), DEC Alpha, MIPS, PA-RISC и IA-64. Обычно порядок байтов выбирается программно во время инициализации операционной системы, но может быть выбран и аппаратно перемычками на материнской плате. В этом случае правильнее говорить о порядке байтов операционной системы. Переключаемый порядок байтов иногда называют англ. bi-endian .

Читайте также:  Штрих коды стран 4260

Смешанный порядок [ править | править код ]

Смешанный порядок байтов (англ. middle-endian) иногда используется при работе с числами, длина которых превышает машинное слово. Число представляется последовательностью машинных слов, которые записываются в формате, естественном для данной архитектуры, но сами слова следуют в обратном порядке.

В процессорах VAX и ARM используется смешанное представление для длинных вещественных чисел.

Пример [ править | править код ]

Далее приведён пример, в котором описывается размещение 4-байтового числа в ОЗУ ЭВМ, доступ к которому может производиться и как к 32-разрядному слову, и побайтно.

Все числа записаны в 16-ричной системе счисления.

Число: 0xA1B2C3D4
Представление A 1 ∗ 1000000 16 + B 2 ∗ 10000 16 + C 3 ∗ 100 16 + D 4 ∗ 1 16 = D 4 C 3 B 2 A 1 <displaystyle A1*1000000_<16>+B2*10000_<16>+C3*100_<16>+D4*1_<16>=D4C3B2A1> 161 ∗ 16 10 6 + 178 ∗ 16 10 4 + 195 ∗ 16 10 2 + 212 10 = 2712847316 10 <displaystyle 161*16_<10>^<6>+178*16_<10>^<4>+195*16_<10>^<2>+212_<10>=2712847316_<10>>
Порядок от младшего к старшему (little-endian) D 4 16 , C 3 16 , B 2 16 , A 1 16 <displaystyle D4_<16>,C3_<16>,B2_<16>,A1_<16>> 212 10 , 195 10 , 178 10 , 161 10 <displaystyle 212_<10>,195_<10>,178_<10>,161_<10>>
Порядок от старшего к младшему (big-endian) A 1 16 , B 2 16 , C 3 16 , D 4 16 <displaystyle A1_<16>,B2_<16>,C3_<16>,D4_<16>> 161 10 , 178 10 , 195 10 , 212 10 <displaystyle 161_<10>,178_<10>,195_<10>,212_<10>>
Порядок, принятый в PDP-11 (PDP-endian) B 2 16 , A 1 16 , D 4 16 , C 3 16 <displaystyle B2_<16>,A1_<16>,D4_<16>,C3_<16>> 178 10 , 161 10 , 212 10 , 195 10 <displaystyle 178_<10>,161_<10>,212_<10>,195_<10>>

Определение порядка байтов [ править | править код ]

Порядок байтов в конкретной машине можно определить с помощью программы на языке Си (testbyteorder.c):

Результаты запуска на big-endian машине (SPARC):

Результаты запуска на little-endian машине (x86):

Вещественные числа [ править | править код ]

Хранение вещественных чисел может зависеть от порядка байт; так, на x86 используются форматы IEEE 754 со знаком и порядком числа в старших байтах.

Юникод [ править | править код ]

Если Юникод записан в виде UTF-16 или UTF-32, то порядок байтов является существенным. Одним из способов обозначения порядка байтов в юникодовых текстах является постановка в начале специального символа BOM (byte order mark, маркер последовательности байтов, U+FEFF) — «перевёрнутый» вариант этого символа (U+FFFE) не существует и не допускается в текстах.

Символ U+FEFF изображается в UTF-16 последовательностью байтов 0xFE 0xFF (big-endian) или 0xFF 0xFE (little-endian), а в UTF-32 — последовательностью 0x00 0x00 0xFE 0xFF (big-endian) или 0xFF 0xFE 0x00 0x00 (little-endian).

Проблемы совместимости и конвертация [ править | править код ]

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

Для преобразования между сетевым порядком байтов (англ. network byte order ), который всегда big-endian, и порядком байтов, использующимся на машине (англ. host byte order ), стандарт POSIX предусматривает функции htonl() , htons() , ntohl() , ntohs() :

  • uint32_t htonl(uint32_t hostlong); — конвертирует 32-битную беззнаковую величину из локального порядка байтов в сетевой;
  • uint16_t htons(uint16_t hostshort); — конвертирует 16-битную беззнаковую величину из локального порядка байтов в сетевой;
  • uint32_t ntohl(uint32_t netlong); — конвертирует 32-битную беззнаковую величину из сетевого порядка байтов в локальный;
  • uint16_t ntohs(uint16_t netshort); — конвертирует 16-битную беззнаковую величину из сетевого порядка байтов в локальный.

В случае совпадения текущего порядка байтов и сетевого функции могут быть «пустыми» (то есть, не менять порядка байтов). Стандарт также допускает, чтобы эти функции были реализованы макросами.

Существует много языков и библиотек со средствами конвертации в оба основных порядка байт и обратно.

Ядро Linux: le16_to_cpu(), cpu_to_be32(), cpu_to_le16p(), и так далее;

Ядро FreeBSD: htobe16(), le32toh(), и так далее;

Инструменты пользователя

Инструменты сайта

Содержание

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

Кроме того, рассматриваются операции сдвигов «, ».

Читайте также:  Земана антималваре официальный сайт

Запись многобайтового числа из памяти компьютера в файл или передача по сети требует соблюдения соглашений о том, какой из байтов является старшим, а какой младшим. Прямая запись ячеек памяти приводит к возможным проблемам при переносе приложения с платформы на платформу. Варианты записи: от старшего к младшему или (англ. big-endian, дословно: «тупоконечный»): этот порядок является стандартным для протоколов TCP/IP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня, разработанных для использования поверх TCP/IP. Поэтому, порядок байтов от старшего к младшему часто называют сетевым порядком байтов (англ. network byte order). От младшего к старшему или (англ. little-endian, дословно: «остроконечный»): запись начинается с младшего и заканчивается старшим. Этот порядок записи принят в памяти персональных компьютеров с x86-процессорами, в связи с чем иногда его называют интеловский порядок байтов.

Чтобы получить значение младщего слова (OWORD)

Считать старшим битом самую левую единицу – ошибочно, в противном случае в системе со знаком все числа будут или нулем, или отрицательными числами.

Мы знаем, что считать можно до бесконечности, а потому при записи числа на листочке количество знаков может быть неограниченным. Понятие "старший" возникает только тогда, когда есть некоторое ограничение на количество записываемых символов (разрядов). Поэтому старший бит – это самый левый бит в записи N-битного числа, содержащей N разрядов (которые при необходимости слева добираются нулями). Просто глядя на число нельзя сказать, какой бит у него старший, нужно ещё знать, во сколько разрядов мы его хотим записать. Т.е. если мы число 128 записываем в переменную типа unsigned char (8 бит), то cтаршим битом будет единица, а если записываем в unsigned int (16 или 32 бита в зависимости от платформы), то старшим битом будет 0.

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

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

потому что все разряды (кроме шестого) в одном из двух операндов имеют значение 1.

Заметим, что, поскольку нулевой разряд в обоих операндах имеет значение 1, нулевой разряд результата имеет значение 0.

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

Таким образом, х«2 сдвигает х влево на 2 позиции, заполняя освобождающиеся позиции нулями (эквивалентно умножению на 4).

Для значений без знака имеем

Эти две операции выполняют сдвиг, а также эффективное умножение и деление на степени числа 2.

Комментарии к коду.

Для понимания побитовых операторов необходимо свободно уметь работать с двоичным представлением чисел. Если это не так, остается только надеяться, что данные операторы не часто вам будут попадаться в вашей практике. Ниже следует перечень побитовых операторов с примерами их применения (примеры и результаты даны, так же, и в бинарной (двоичной) форме):

Таблица. Побитовые операторы.

Принцип работы побитовых операторов достаточно прост: JavaScript рассматривает последовательно каждый бит операндов, выполняет над ними одну из логических операций (исходя из того, что 1 – true, a 0 – false) и формирует бит результата. Исключением являются лишь операции побитового сдвига. Рассмотрим небольшой пример применения побитовых операций – определение четности числа. Если число является четным, то его первый (крайний правый) бит равен "0" и операция "&" с числом "1" вернет значение "0". Исходя из этого, напишем скрипт:

Листинг: определение четности числа

Если в результате получится значение false, то заданное число является нечетным, в противном случае, число является четным.