- Дневники чайника. Чтива 0, виток0
- Системы счисления и устройство памяти. Второй день
- Десятичная — Decimal (Dec или буква «d»)
- Двоичная система счисления — Binary (Bin или буква «b»)
- Шестнадцатиричная система счисления — Hexadecimal (Hex или буква «h»)
- Первая полезная программа
- Эксперимент 01 (prax01.com)
- О битах, байтах и скорости интернет соединения
- Сокеты Windows. Порядок байтов Windows Sockets: Byte Ordering
- Порядок байтов Byte Ordering
- Упорядоченность больших и Little-Endian байт Big- and Little-Endian Byte Ordering
- Когда необходимо преобразовать порядок байтов When You Must Convert Byte Orders
- Если не нужно преобразовывать порядок байтов When You Do Not Have to Convert Byte Orders
- Пример преобразования Byte-Order A Byte-Order Conversion Example
- Функции преобразования Byte-Order сокеты Windows Windows Sockets Byte-Order Conversion Functions
Дневники чайника. Чтива 0, виток0
Системы счисления и устройство памяти.
Второй день
Поскольку компьютер в основе своей имеет только 0 и 1, на первых этапах освоения ассемблера (может быть, год) нам будут нужны только целые числа, мало того, очень долго можно работать всего лишь с положительными целыми числами, о которых здесь и пойдёт речь.
Только целые и только положительные.
Возможно, вы проходили эту тему в школе, и кто-то из вас даже что-то помнит, но начинать нужно именно отсюда.
Нас будут интересовать 3 системы счисления — dec, bin, hex.
Десятичная — Decimal (Dec или буква «d»)
Aрабская система — она называется десятичной, потому что в ней используются 10 символов.
Все значения представляются этими символами. Вы и сами знаете, как пользоваться десятичной системой, так как мы все выросли на ней и каждую минуту чего-нибудь считаем.
Запомни, юнга! В космосе нет верха, нет низа — это всё условности. И то, что у тебя десять пальцев на руках, это всего лишь исключение. У наших бинарных братьев всего два пальца, они смеются над тобой — урод десятипалый :). У них есть на это право, их больше и они старше. С Бинарниками надо дружить, иначе корабль собьют на подходе к первой же станции.
Двоичная система счисления — Binary (Bin или буква «b»)
Нетрудно догадаться, что двоичная система имеет всего два символа 0 и 1.
Компьютер — это очень простой прибор, в нём есть только выключатели — биты (вкл. =1, выкл. =0).
Понятие Bit, скорее всего, произошло от английских слов Binary — двоичная и Digit — цифра. Но поскольку битов о-о-очень много, биты строятся в байты.
Бит может иметь значение 0 или 1.
Байт — это 8 бит, и он может иметь значения от 0000 0000 — ноль, до 1111 1111 — 255 в десятичной системе (пробелы для читаемости). Получается, что у байта 256 значений (всегда считается вместе с нулевым).
Переводить из десятичных цифр в биты (то есть в двоичные цифры) и обратно можно на виндовом калькуляторе (в инженерном режиме). Потренируйтесь пока так. Учить наизусть всю таблицу не нужно, познакомились — уже хорошо. 🙂
Как вы думаете, почему я выделил 2,4,8,16?
Правильно, это «круглые» цифры. В десятичной системе они, конечно, не круглые, но в двоичной получается 10,100,1000,10000. Поэтому десятичная система для компьютерных вычислений не очень подходит. Вместо неё используется.
Шестнадцатиричная система счисления — Hexadecimal (Hex или буква «h»)
Имеет целых 16 символов. Чтоб не придумывать новые символы, в hex используются буквы латинского алфавита.
Я приравняю все hex-символы к десятичным значениям.
В этой системе счисления ноль справа прибавляется при умножении на 16 (десятичных).
Лишние нули слева от числа значения не имеют, так же, как и в математике.
Однако если число начинается с буквы (A-F), ноль слева нужен при наборе программ. Иначе как компилятор будет определять, что началось число? А чтобы не путать числа в разных системах и писать при этом коротко, пишут:
d — десятичные значения
h — шестнадцатиричные значения
b — двоичные значения
Удобно, правда? А вот так?
Неудобно. Поэтому всегда ВСЕ ВЫЧИСЛЕНИЯ ДЕЛАЙТЕ В ОДНОЙ СИСТЕМЕ!
Сам я никогда не перевожу из hex в dec и в bin в уме или на листочке, для этого есть калькулятор. И мне знакома эта растерянность перед новыми цифрами. Но я и не рассчитываю, что стало понятно хоть что-то. Просто вы должны знать, что системы счисления hex & bin существуют. Через месяц практики вы привыкнете к шестнадцатиричной системе как к родной. А вот двоичная будет использоваться только в пределах четырёх байт. На экране монитора мне лишь изредка приходится видеть биты как «01011010», хотя часто их очень не хватает.
Теперь ещё раз про байт.
В байт умещаются ровно два разряда hex-системы счисления! Именно так мы и будем видеть байты. Вспомните наш нулевой эксперимент:
Теперь вы понимаете, что я имел в виду, сказав: «90 здесь 144». Правильнее было бы сказать 90h = 144d.
Байт это 8 бит, и что самое главное, байт — минимально адресуемая ячейка памяти.
Если нужно прочитать информацию, например, из бита 900, то нам нужно обратиться к 112-му байту и посмотреть в нём бит номер 4.
Конечно же, в компьютере физически биты не разделяются пробелами. Вся оперативная память, например, — сплошной поток выключателей :).
Но при отображении биты обычно разделяют на:
байты — 8 бит, две hex-цифры, или
тетрады — 4 бита, одна hex-цифра.
Обратите внимание на запись. Мы нумеруем биты справа налево и обязательно от нуля — это стандарт для учебников и документации. Кроме того, нумерация от нуля имеет математический смысл (разряды нужно осознать!).
Хотя так информацию мы видеть практически не будем. Вместо битов везде будут hex-байты, вот так:
Здесь вынужден заметить: адреса в файле и адреса в оперативной памяти — это совершенно разные вещи.
Далее по тексту я буду грубо писать: «адрес в памяти», под этими словами мы будем подразумевать часть логического адреса, которую принято называть смещением (offset). В рамках наших уроков смещение — вполне достаточный адрес в памяти. Однако смещение — это не полный логический адрес и называть смещение адресом без оговорок — довольно грубо! В следующем витке мы обязательно разберём адресацию памяти в разных режимах процессора, и там я расскажу, что такое сегмент и смещение.
А сейчас запомните. Когда я пишу: адрес в файле, я подразумеваю номер байта в файле от нуля. И это норма. А вот когда я пишу: адрес в памяти, это значит, что речь идёт о части логического адреса, называемой смещением (тоже от нуля).
Да простят меня профи за такую вольность.
Юнга, после обеда я научу тебя писать дельные программы для вспомогательного бортового оборудования. Ты, конечно, пуст, как первая ступень, и ни черта не понял за сегодня, но у меня нет времени рассусоливать, нас давно ждут.
Первая полезная программа
Что там у нас дальше по учебнику? Этого вам пока не надо. Этого я и сам ещё не знаю. Тут слишком много умностей. Нет, пожалуй, продолжу, как предложил Олег Калашников. Пожалуй, лучший подход для любителей практики.
Эксперимент 01 (prax01.com)
Я по-прежнему подразумеваю, что вы используете WinXP и пример должен работать.
Создайте файл с расширением «com» (напомню в FAR’e — Shift+F4). Назвав файл, напечатайте в нём любую букву или цифру, ну, допустим, «1». Сохраните файл (в FAR’e — Esc).
Нет, это ещё не программа, этот файл выполнять не нужно. Откройте в Hiew’e.
Сейчас вы видите 1, если нажать «F4» (Mode), то, как и в тот раз, вы увидите байт в hex-виде. F4 еще раз покажет дизассемблерный код. Если в файле единица, то выглядеть код будет так:
В отличие от команды nop, которую вы уже видели, большинство команд используют предметы для действия.
Предмет, с (или над) которым производится действие, называется операнд.
Операнды в ассемблере для Интел-совместимых процессоров принято разделять запятыми. То есть в некоторых системах или в других языках программирования пишут:
AX xor 44
или вполне может быть такая форма записи:
44,55 xоr AX
Но в x86 ассемблере принято писать так:
Из всего этого главное сейчас усвоить, что операндов не больше трёх (чащё всего 2), они разделяются запятыми и идут после имени команды. Давайте писать настоящую программу на ассемблере.
В Hiew’e (когда вы видите дизассемблерный код нашего файла) нажмите F3 и затем Enter. Теперь можно набирать программу на ассемблере (символ «1» в файле должен стереться). Каждая инструкция вводится Enter’ом и превращается в строку, если нет явной ошибки. Пробелы нужны только для удобства, поэтому неважно, сколько их. Пишите как хотите, строчными или прописными буквами, но только по-англицки. 🙂
Вот код программы, его нужно набрать:
Когда всё напишете, нажмите один раз Esc, чтобы прекратить ассемблирование, и F9, чтобы сохранить файл.
Это был весь код программы, которая должна выводить строку на экран! Круто, правда? Только не хватает самой строки.
Для того, чтоб вписать строку, нужно открыть файл в текстовом редакторе (в FAR’e — F4).
Допишите после всех закорючек (только не сотрите ничего) любую текстовую строку и в конце поставьте знак $.
Это может выглядеть примерно так:
Закорючки будут другие, но вид такой. Сохраните программу. Откройте снова в Hiew’e.
Принято так, что после точки с запятой идёт комментарий, просто пояснение для людей. В этом примере я откомментировал все строки кода программы. Только вам от этого пока не легче.
Видите, начиная с адреса в файле 0000000Dh, появились команды, которые вы не писали, это всего лишь строка текста. Её процессор выполнять не будет только потому, что перед строкой текста стоит код завершения (int 20).
Запустите программу (можно из проводника). Если компьютер с вами поздоровался — я вас тоже поздравляю! Значит, у вас есть шанс научить его делать и более сложные вещи.
Вы увидите окно DOS-приложения с текстом: Good Day! Нажатие на любую клавишу вызовет выход из программы. |
Если же этого не произошло — не расстраивайтесь. Перепроверьте всё несколько раз, может быть, вы опечатались. Прочитайте «Аннотацию» в последней главе или комментарии. Я пока ничего подобного не написал, но, возможно, когда-нибудь придётся. Ведь у нас нет гарантии, что новые твАрения MS или других «рук» не изменят ситуацию в худшую сторону. Хотя, будем надеяться, что программа заработает и на новых OS’ях и процессорах.
«$» не выводится. Хм, интересно :/ Это условный символ конца строки?
Да, но в windows мы будем использовать нулевой байт (00h) для этой же цели.
Вот, уже получилась полнофункциональная программа для DOS, которая будет работать и в Windows.
Прямо так и вижу следующие «почему»:
Почему mov?
Почему ah?
Почему 9?
И вообще, что это за подпрограммы-прерывания int 16, int 21, int 20.
Последний вопрос меня тоже очень огорчил, когда впервые столкнулся с этим примером. Я ожидал получить программу на чистом Ассемблере, а был вынужден использовать какие-то непонятные функции, которых не писал.
На самом деле вывод строки на экран без специальной DOS-функции ничуть не сложнее. Мы используем именно такой способ из-за того, что он наиболее схож с программированием под Win. Здесь было бы аккуратнее и быстрее выводить на экран без специальной подпрограммы DOS-функций.
Но ДОС в прошлом, а нас ждёт Win32.
Cамое главное не переживать, если вы вдруг не понимаете что здесь к чему, поверьте, через пару уроков вы полностью поймёте эту программу.
Мы завтра весь день будем искать ответ на вопрос «Почему ah», так как этот «почему» — самый важный во всём ассемблере. Серьёзно!
О битах, байтах и скорости интернет соединения
Для начала попробуем разобраться, что же такое биты и байты. Бит это самая наименьшая единица измерения количества информации. Наравне с битом активно используется байт. Байт равен 8 бит. Попробуем изобразить это наглядно на следующей диаграмме.
Думаю, с этим все понятно и не имеет смысла останавливаться подробнее. Так как бит и байт это очень маленькие величины, то в основном они используются с приставками кило, мега и гига. Наверняка вы слышали о них еще со школьной программы. Общепринятые единицы и их сокращения мы соединили в таблицу.
Название | Аббревиатура английская | Аббревиатура русская | Значение |
---|---|---|---|
бит | bit (b) | б | 0 или 1 |
байт | Byte (B) | Б | 8 бит |
килобит | kbit (kb) | кбит (кб) | 1000 бит |
килобайт | KByte (KB) | КБайт (KБ) | 1024 байта |
мегабит | mbit (mb) | мбит (мб) | 1000 килобит |
мегабайт | MByte (MB) | МБайт (МБ) | 1024 килобайта |
гигабит | gbit (gb) | гбит (гб) | 1000 мегабит |
гигабайт | GByte (GB) | ГБайт (ГБ) | 1024 мегабайта |
Теперь попробуем определиться с величинами измерения скорости интернет соединения.
Говоря понятным языком, скорость подключения это количество получаемой или отправляемой вашим компьютером информации в единицу времени. В качестве единицы времени в данном случае принято считать секунду а в качестве количества информации кило или мегабит.
Таким образом, если ваша скорость 128 Kbps это означает, что ваше соединение имеет пропускную способность 128 килобит в секунду или же 16 килобайт в секунду.
Много это или мало судить вам. Для того чтобы более материально почувствовать вашу скорость рекомендую воспользоваться нашими тестами. Определить время, необходимое для закачки файла, определенного вами размера, при вашей скорости подключения. Также вы можете посмотреть, файл какого объема вы сможете скачать за определенный вами период времени при вашей скорости подключения.
Используя наши тесты необходимо помнить и учитывать, что наш сервер, на котором собственно и расположены все эти тесты находится от вашего компьютера достаточно далеко и соответственно на результатах может сказываться как загруженность нашего сервера (на нашем сайте в часы пик одновременно производят замер скорости соединения более 1000 человек), так и загруженность интернет линий.
Если бы наш сервер стоял за одним столом с вашим компьютером и они были бы подключены друг к другу одним проводом, тогда можно было бы вести речь о наиболее точных результатах. В нашем же случае, как показывает практика, подключение вашего компьютера к нашему серверу для тестирования происходит в среднем через 10 других серверов.
Сокеты Windows. Порядок байтов Windows Sockets: Byte Ordering
В этой статье и двух сопутствующих статьях объясняются некоторые проблемы, связанные с программированием Windows Sockets. This article and two companion articles explain several issues in Windows Sockets programming. В этой статье описывается порядок байтов. This article covers byte ordering. Другие проблемы описаны в статьях: сокеты Windows: Блокировка и сокеты Windows: преобразование строк. The other issues are covered in the articles: Windows Sockets: Blocking and Windows Sockets: Converting Strings.
Если вы используете или наследуете от класса CAsyncSocket, вам придется самостоятельно управлять этими проблемами. If you use or derive from class CAsyncSocket, you will need to manage these issues yourself. Если вы используете или наследуете от класса CSocket, MFC управляет ими. If you use or derive from class CSocket, MFC manages them for you.
Порядок байтов Byte Ordering
Различные архитектуры компьютеров иногда хранят данные, используя различные порядки байтов. Different machine architectures sometimes store data using different byte orders. Например, компьютеры на базе технологии Intel хранят данные в противоположном порядке компьютеров Macintosh (Motorola). For example, Intel-based machines store data in the reverse order of Macintosh (Motorola) machines. Порядок байтов Intel, называемый прямым порядком байтов, также является обратным по отношению к сетевому стандарту с обратным порядковым порядком байтов. The Intel byte order, called «little-Endian,» is also the reverse of the network standard «big-Endian» order. Эти термины объясняются в следующей таблице. The following table explains these terms.
Упорядоченность больших и Little-Endian байт Big- and Little-Endian Byte Ordering
Порядок байтов Byte ordering | Значение Meaning |
---|---|
Big-Endian Big-Endian | Наиболее значимый байт находится в левом конце слова. The most significant byte is on the left end of a word. |
Little-Endian Little-Endian | Наиболее значимый байт находится в правом конце слова. The most significant byte is on the right end of a word. |
Как правило, не нужно беспокоиться о преобразовании порядка байтов для данных, отправляемых и получаемых по сети, но существуют ситуации, в которых необходимо преобразовать заказы байтов. Typically, you do not have to worry about byte-order conversion for data that you send and receive over the network, but there are situations in which you must convert byte orders.
Когда необходимо преобразовать порядок байтов When You Must Convert Byte Orders
Порядок байтов необходимо преобразовать в следующих ситуациях: You need to convert byte orders in the following situations:
Вы передаете сведения, которые должны интерпретироваться сетью, а не данные, отправляемые на другой компьютер. You are passing information that needs to be interpreted by the network, as opposed to the data you are sending to another machine. Например, можно передать порты и адреса, которые должны быть понятны сети. For example, you might pass ports and addresses, which the network must understand.
Серверное приложение, с которым вы обмениваетесь данными, не является приложением MFC (и у вас нет исходного кода). The server application with which you are communicating is not an MFC application (and you do not have source code for it). Это вызывает преобразование порядка байтов, если два компьютера не имеют одинаковый порядок байтов. This calls for byte order conversions if the two machines do not share the same byte ordering.
Если не нужно преобразовывать порядок байтов When You Do Not Have to Convert Byte Orders
Вы можете избежать операций преобразования порядка байтов в следующих ситуациях: You can avoid the work of converting byte orders in the following situations:
Компьютеры на обоих концах могут согласиться не менять байты, и оба компьютера используют одинаковый порядок байтов. The machines on both ends can agree not to swap bytes, and both machines use the same byte order.
Сервер, с которым вы обмениваетесь данными, является приложением MFC. The server you are communicating with is an MFC application.
У вас есть исходный код для сервера, с которым вы обмениваетесь данными, поэтому вы можете явно определить, нужно ли преобразовывать побайтовые заказы. You have source code for the server you’re communicating with, so you can tell explicitly whether you must convert byte orders or not.
Сервер можно перенести в MFC. You can port the server to MFC. Это довольно просто, и результат обычно меньше, чем быстрее. This is fairly easy to do, and the result is usually smaller, faster code.
Работая с CAsyncSocket, необходимо самостоятельно управлять любыми необходимыми преобразованиями порядка байтов. Working with CAsyncSocket, you must manage any necessary byte-order conversions yourself. Сокеты Windows стандартизируют модель порядка байтов с обратным порядком следования и предоставляют функции для преобразования между этим заказом и другими. Windows Sockets standardizes the «big-Endian» byte-order model and provides functions to convert between this order and others. Однако CArchive, который используется с CSocket, использует противоположный порядок («с прямым порядком следования байтов)», но CArchive позаботится о преобразованиях порядка байтов. CArchive, however, which you use with CSocket, uses the opposite («little-Endian») order, but CArchive takes care of the details of byte-order conversions for you. Используя это стандартное упорядочение в приложениях или используя функции преобразования порядка следования байтов в Windows Sockets, можно сделать код более переносимым. By using this standard ordering in your applications, or using Windows Sockets byte-order conversion functions, you can make your code more portable.
Идеальным вариантом использования сокетов MFC является ситуация, когда вы пишете оба конца связи: использование MFC на обоих концах. The ideal case for using MFC sockets is when you are writing both ends of the communication: using MFC at both ends. Если вы создаете приложение, которое будет взаимодействовать с приложениями, не использующими MFC, например с FTP-сервером, вам, вероятно, придется самостоятельно управлять обменом байтов перед передачей данных в архивный объект, используя подпрограммы преобразования сокетов Windows нтохс, нтохл, хтонс и хтонл. If you are writing an application that will communicate with non-MFC applications, such as an FTP server, you will probably need to manage byte-swapping yourself before you pass data to the archive object, using the Windows Sockets conversion routines ntohs, ntohl, htons, and htonl. Ниже в этой статье приводятся примеры этих функций, используемых при взаимодействии с приложениями, не использующими MFC. An example of these functions used in communicating with a non-MFC application appears later in this article.
Если другой конец обмена данными не является приложением MFC, необходимо также избегать потоковой передачи объектов C++, производных от, CObject в архив, так как получатель не сможет их обрабатывать. When the other end of the communication is not an MFC application, you also must avoid streaming C++ objects derived from CObject into your archive because the receiver will not be able to handle them. См. Примечание в разделе сокеты Windows: Использование сокетов с архивами. See the note in Windows Sockets: Using Sockets with Archives.
Дополнительные сведения о побайтовых заказах см. в разделе Спецификация сокетов Windows, доступная в Windows SDK. For more information about byte orders, see the Windows Sockets specification, available in the Windows SDK.
Пример преобразования Byte-Order A Byte-Order Conversion Example
В следующем примере показана функция сериализации для CSocket объекта, который использует Архив. The following example shows a serialization function for a CSocket object that uses an archive. Он также иллюстрирует использование функций преобразования порядка байтов в API-интерфейсе Windows Sockets. It also illustrates using the byte-order conversion functions in the Windows Sockets API.
В этом примере представлен сценарий, в котором выполняется запись клиента, взаимодействующего с серверным приложением, не являющимся MFC, для которого отсутствует доступ к исходному коду. This example presents a scenario in which you are writing a client that communicates with a non-MFC server application for which you have no access to the source code. В этом сценарии необходимо предположить, что сервер, не являющийся сервером MFC, использует стандартный сетевой порядок байтов. In this scenario, you must assume that the non-MFC server uses standard network byte order. В отличие от этого, клиентское приложение MFC использует CArchive объект с CSocket объектом и CArchive использует порядок байтов с прямым порядком следования, противоположный стандарту сети. In contrast, your MFC client application uses a CArchive object with a CSocket object, and CArchive uses «little-Endian» byte order, the opposite of the network standard.
Предположим, что сервер, не относящийся к MFC, с которым планируется обмениваться данными, имеет установленный протокол для пакета сообщений, который выглядит следующим образом: Suppose the non-MFC server with which you plan to communicate has an established protocol for a message packet like the following:
В терминах MFC это выражение выражается следующим образом: In MFC terms, this would be expressed as follows:
В C++, по struct сути, это то же самое, что и класс. In C++, a struct is essentially the same thing as a class. Message Структура может иметь функции элементов, например Serialize функцию члена, объявленную выше. The Message structure can have member functions, such as the Serialize member function declared above. Serialize Функция члена может выглядеть следующим образом: The Serialize member function might look like this:
В этом примере вызывается преобразование порядка байтов данных, так как существует четкое несоответствие порядка байтов серверного приложения, не относящегося к MFC, на одном конце и CArchive используемого в клиентском приложении MFC на другом конце. This example calls for byte-order conversions of data because there is a clear mismatch between the byte ordering of the non-MFC server application on one end and the CArchive used in your MFC client application on the other end. В примере показаны некоторые функции преобразования порядка байтов, предоставляемые сокетами Windows. The example illustrates several of the byte-order conversion functions that Windows Sockets supplies. Эти функции описаны в следующей таблице. The following table describes these functions.
Функции преобразования Byte-Order сокеты Windows Windows Sockets Byte-Order Conversion Functions
Функция Function | Назначение Purpose |
---|---|
нтохс ntohs | Преобразование 16-разрядного количества из сетевого байтового порядка в порядок размещения байтов (с обратным порядком байтов (Big-endian). Convert a 16-bit quantity from network byte order to host byte order (big-Endian to little-Endian). |
нтохл ntohl | Преобразование 32-разрядного количества из сетевого байтового порядка в порядковый номер размещения в байтах (с обратным порядком байтов). Convert a 32-bit quantity from network byte order to host byte order (big-Endian to little-Endian). |
хтонс Htons | Преобразует 16-разрядное количество из байтового порядка узла в сетевой байтовый порядок (с прямым порядком байтов с обратным порядком байтов). Convert a 16-bit quantity from host byte order to network byte order (little-Endian to big-Endian). |
хтонл Htonl | Преобразование 32-разрядного количества из байтового порядка узла в сетевой байтовый порядок (с прямым порядком байтов с обратным порядком байтов). Convert a 32-bit quantity from host byte order to network byte order (little-Endian to big-Endian). |
Еще одной точкой этого примера является то, что если приложение сокета на другом конце связи является приложением, не являющимся MFC, необходимо избегать выполнения следующих действий: Another point of this example is that when the socket application on the other end of the communication is a non-MFC application, you must avoid doing something like the following:
где pMsg — указатель на объект C++, производный от класса CObject . where pMsg is a pointer to a C++ object derived from class CObject . При этом будут отправлены дополнительные сведения MFC, связанные с объектами, и сервер не сможет понять его, как если бы он был приложением MFC. This will send extra MFC information associated with objects and the server will not understand it, as it would if it were an MFC application.
Дополнительные сведения см. в разделе: For more information, see: