Double word тип данных

Обновлено: 02.07.2024

The data types supported by Windows are used to define function return values, function and message parameters, and structure members. They define the size and meaning of these elements. For more information about the underlying C/C++ data types, see Data Type Ranges.

The following table contains the following types: character, integer, Boolean, pointer, and handle. The character, integer, and Boolean types are common to most C compilers. Most of the pointer-type names begin with a prefix of P or LP. Handles refer to a resource that has been loaded into memory.

For more information about handling 64-bit integers, see Large Integers.

A handle to an object.

This type is declared in WinNT.h as follows:

typedef PVOID HANDLE;

This type is declared in WinDef.h as follows:

typedef HANDLE HBITMAP;

This type is declared in WinDef.h as follows:

typedef HANDLE HBRUSH;

This type is declared in WinDef.h as follows:

typedef HANDLE HCOLORSPACE;

A handle to a dynamic data exchange (DDE) conversation.

This type is declared in Ddeml.h as follows:

typedef HANDLE HCONV;

A handle to a DDE conversation list.

This type is declared in Ddeml.h as follows:

typedef HANDLE HCONVLIST;

This type is declared in WinDef.h as follows:

typedef HICON HCURSOR;

This type is declared in WinDef.h as follows:

typedef HANDLE HDC;

A handle to DDE data.

This type is declared in Ddeml.h as follows:

typedef HANDLE HDDEDATA;

This type is declared in WinDef.h as follows:

typedef HANDLE HDESK;

A handle to an internal drop structure.

This type is declared in ShellApi.h as follows:

typedef HANDLE HDROP;

A handle to a deferred window position structure.

This type is declared in WinUser.h as follows:

typedef HANDLE HDWP;

This type is declared in WinDef.h as follows:

typedef HANDLE HENHMETAFILE;

This type is declared in WinDef.h as follows:

typedef int HFILE;

This type is declared in WinDef.h as follows:

typedef HANDLE HFONT;

A handle to a GDI object.

This type is declared in WinDef.h as follows:

typedef HANDLE HGDIOBJ;

A handle to a global memory block.

This type is declared in WinDef.h as follows:

typedef HANDLE HGLOBAL;

This type is declared in WinDef.h as follows:

typedef HANDLE HHOOK;

This type is declared in WinDef.h as follows:

typedef HANDLE HICON;

A handle to an instance. This is the base address of the module in memory.

HMODULE and HINSTANCE are the same today, but represented different things in 16-bit Windows.

This type is declared in WinDef.h as follows:

typedef HANDLE HINSTANCE;

A handle to a registry key.

This type is declared in WinDef.h as follows:

typedef HANDLE HKEY;

An input locale identifier.

This type is declared in WinDef.h as follows:

typedef HANDLE HKL;

A handle to a local memory block.

This type is declared in WinDef.h as follows:

typedef HANDLE HLOCAL;

This type is declared in WinDef.h as follows:

typedef HANDLE HMENU;

This type is declared in WinDef.h as follows:

typedef HANDLE HMETAFILE;

A handle to a module. The is the base address of the module in memory.

HMODULE and HINSTANCE are the same in current versions of Windows, but represented different things in 16-bit Windows.

This type is declared in WinDef.h as follows:

typedef HINSTANCE HMODULE;

A handle to a display monitor.

This type is declared in WinDef.h as follows:

if(WINVER >= 0x0500) typedef HANDLE HMONITOR;

A handle to a palette.

This type is declared in WinDef.h as follows:

typedef HANDLE HPALETTE;

This type is declared in WinDef.h as follows:

typedef HANDLE HPEN;

The return codes used by COM interfaces. For more information, see Structure of the COM Error Codes. To test an HRESULT value, use the FAILED and SUCCEEDED macros.

This type is declared in WinNT.h as follows:

typedef LONG HRESULT;

This type is declared in WinDef.h as follows:

typedef HANDLE HRGN;

A handle to a resource.

This type is declared in WinDef.h as follows:

typedef HANDLE HRSRC;

A handle to a DDE string.

This type is declared in Ddeml.h as follows:

typedef HANDLE HSZ;

This type is declared in WinDef.h as follows:

typedef HANDLE WINSTA;

This type is declared in WinDef.h as follows:

typedef HANDLE HWND;

A 32-bit signed integer. The range is -2147483648 through 2147483647 decimal.

This type is declared in WinDef.h as follows:

typedef int INT;

A signed integer type for pointer precision. Use when casting a pointer to an integer to perform pointer arithmetic.

This type is declared in BaseTsd.h as follows:

This type is declared in BaseTsd.h as follows:

typedef signed char INT8;

A 16-bit signed integer.

This type is declared in BaseTsd.h as follows:

typedef signed short INT16;

A 32-bit signed integer. The range is -2147483648 through 2147483647 decimal.

This type is declared in BaseTsd.h as follows:

typedef signed int INT32;

A 64-bit signed integer. The range is -9223372036854775808 through 9223372036854775807 decimal.

This type is declared in BaseTsd.h as follows:

typedef signed __int64 INT64;

A language identifier. For more information, see Language Identifiers.

This type is declared in WinNT.h as follows:

typedef WORD LANGID;

A locale identifier. For more information, see Locale Identifiers.

This type is declared in WinNT.h as follows:

typedef DWORD LCID;

A locale information type. For a list, see Locale Information Constants.

This type is declared in WinNls.h as follows:

typedef DWORD LCTYPE;

This type is declared in WinNls.h as follows:

typedef DWORD LGRPID;

A 32-bit signed integer. The range is -2147483648 through 2147483647 decimal.

This type is declared in WinNT.h as follows:

typedef long LONG;

A 64-bit signed integer. The range is -9223372036854775808 through 9223372036854775807 decimal.

This type is declared in WinNT.h as follows:

A signed long type for pointer precision. Use when casting a pointer to a long to perform pointer arithmetic.

This type is declared in BaseTsd.h as follows:

A 32-bit signed integer. The range is -2147483648 through 2147483647 decimal.

This type is declared in BaseTsd.h as follows:

typedef signed int LONG32;

A 64-bit signed integer. The range is -9223372036854775808 through 9223372036854775807 decimal.

This type is declared in BaseTsd.h as follows:

typedef __int64 LONG64;

A message parameter.

This type is declared in WinDef.h as follows:

typedef LONG_PTR LPARAM;

This type is declared in WinDef.h as follows:

typedef BOOL far *LPBOOL;

This type is declared in WinDef.h as follows:

typedef BYTE far *LPBYTE;

This type is declared in WinDef.h as follows:

typedef DWORD *LPCOLORREF;

This type is declared in WinNT.h as follows:

typedef __nullterminated CONST CHAR *LPCSTR;

An LPCWSTR if UNICODE is defined, an LPCSTR otherwise. For more information, see Windows Data Types for Strings.

This type is declared in WinNT.h as follows:

A pointer to a constant of any type.

This type is declared in WinDef.h as follows:

typedef CONST void *LPCVOID;

A pointer to a constant null-terminated string of 16-bit Unicode characters. For more information, see Character Sets Used By Fonts.

This type is declared in WinNT.h as follows:

typedef CONST WCHAR *LPCWSTR;

This type is declared in WinDef.h as follows:

typedef DWORD *LPDWORD;

This type is declared in WinDef.h as follows:

typedef HANDLE *LPHANDLE;

This type is declared in WinDef.h as follows:

typedef int *LPINT;

This type is declared in WinDef.h as follows:

typedef long *LPLONG;

This type is declared in WinNT.h as follows:

typedef CHAR *LPSTR;

An LPWSTR if UNICODE is defined, an LPSTR otherwise. For more information, see Windows Data Types for Strings.

This type is declared in WinNT.h as follows:

A pointer to any type.

This type is declared in WinDef.h as follows:

typedef void *LPVOID;

This type is declared in WinDef.h as follows:

typedef WORD *LPWORD;

A pointer to a null-terminated string of 16-bit Unicode characters. For more information, see Character Sets Used By Fonts.

This type is declared in WinNT.h as follows:

typedef WCHAR *LPWSTR;

Signed result of message processing.

This type is declared in WinDef.h as follows:

typedef LONG_PTR LRESULT;

This type is declared in WinDef.h as follows:

typedef BOOL *PBOOL;

This type is declared in WinNT.h as follows:

typedef BOOLEAN *PBOOLEAN;

This type is declared in WinDef.h as follows:

typedef BYTE *PBYTE;

This type is declared in WinNT.h as follows:

typedef CHAR *PCHAR;

This type is declared in WinNT.h as follows:

typedef CONST CHAR *PCSTR;

A PCWSTR if UNICODE is defined, a PCSTR otherwise. For more information, see Windows Data Types for Strings.

This type is declared in WinNT.h as follows:

A pointer to a constant null-terminated string of 16-bit Unicode characters. For more information, see Character Sets Used By Fonts.

This type is declared in WinNT.h as follows:

typedef CONST WCHAR *PCWSTR;

This type is declared in WinDef.h as follows:

typedef DWORD *PDWORD;

This type is declared in WinNT.h as follows:

typedef DWORDLONG *PDWORDLONG;

This type is declared in BaseTsd.h as follows:

typedef DWORD_PTR *PDWORD_PTR;

This type is declared in BaseTsd.h as follows:

typedef DWORD32 *PDWORD32;

This type is declared in BaseTsd.h as follows:

typedef DWORD64 *PDWORD64;

This type is declared in WinDef.h as follows:

typedef FLOAT *PFLOAT;

This type is declared in BaseTsd.h as follows:

This type is declared in WinNT.h as follows:

typedef HANDLE *PHANDLE;

This type is declared in WinDef.h as follows:

typedef HKEY *PHKEY;

This type is declared in WinDef.h as follows:

typedef int *PINT;

This type is declared in BaseTsd.h as follows:

typedef INT_PTR *PINT_PTR;

This type is declared in BaseTsd.h as follows:

typedef INT8 *PINT8;

This type is declared in BaseTsd.h as follows:

typedef INT16 *PINT16;

This type is declared in BaseTsd.h as follows:

typedef INT32 *PINT32;

This type is declared in BaseTsd.h as follows:

typedef INT64 *PINT64;

This type is declared in WinNT.h as follows:

typedef PDWORD PLCID;

This type is declared in WinNT.h as follows:

typedef LONG *PLONG;

This type is declared in WinNT.h as follows:

typedef LONGLONG *PLONGLONG;

This type is declared in BaseTsd.h as follows:

typedef LONG_PTR *PLONG_PTR;

This type is declared in BaseTsd.h as follows:

typedef LONG32 *PLONG32;

This type is declared in BaseTsd.h as follows:

typedef LONG64 *PLONG64;

A 32-bit pointer. On a 32-bit system, this is a native pointer. On a 64-bit system, this is a truncated 64-bit pointer.

This type is declared in BaseTsd.h as follows:

A 64-bit pointer. On a 64-bit system, this is a native pointer. On a 32-bit system, this is a sign-extended 32-bit pointer.

Note that it is not safe to assume the state of the high pointer bit.

This type is declared in BaseTsd.h as follows:

A signed pointer.

This type is declared in BaseTsd.h as follows:

An unsigned pointer.

This type is declared in BaseTsd.h as follows:

This type is declared in WinNT.h as follows:

typedef SHORT *PSHORT;

This type is declared in BaseTsd.h as follows:

typedef SIZE_T *PSIZE_T;

This type is declared in BaseTsd.h as follows:

typedef SSIZE_T *PSSIZE_T;

This type is declared in WinNT.h as follows:

typedef CHAR *PSTR;

This type is declared in WinNT.h as follows:

typedef TBYTE *PTBYTE;

This type is declared in WinNT.h as follows:

typedef TCHAR *PTCHAR;

A PWSTR if UNICODE is defined, a PSTR otherwise. For more information, see Windows Data Types for Strings.

This type is declared in WinNT.h as follows:

This type is declared in WinDef.h as follows:

typedef UCHAR *PUCHAR;

This type is declared in BaseTsd.h as follows:

This type is declared in WinDef.h as follows:

typedef UINT *PUINT;

This type is declared in BaseTsd.h as follows:

typedef UINT_PTR *PUINT_PTR;

This type is declared in BaseTsd.h as follows:

typedef UINT8 *PUINT8;

This type is declared in BaseTsd.h as follows:

typedef UINT16 *PUINT16;

This type is declared in BaseTsd.h as follows:

typedef UINT32 *PUINT32;

This type is declared in BaseTsd.h as follows:

typedef UINT64 *PUINT64;

This type is declared in WinDef.h as follows:

typedef ULONG *PULONG;

This type is declared in WinDef.h as follows:

typedef ULONGLONG *PULONGLONG;

This type is declared in BaseTsd.h as follows:

typedef ULONG_PTR *PULONG_PTR;

This type is declared in BaseTsd.h as follows:

typedef ULONG32 *PULONG32;

This type is declared in BaseTsd.h as follows:

typedef ULONG64 *PULONG64;

This type is declared in WinDef.h as follows:

typedef USHORT *PUSHORT;

A pointer to any type.

This type is declared in WinNT.h as follows:

typedef void *PVOID;

This type is declared in WinNT.h as follows:

typedef WCHAR *PWCHAR;

This type is declared in WinDef.h as follows:

typedef WORD *PWORD;

A pointer to a null-terminated string of 16-bit Unicode characters. For more information, see Character Sets Used By Fonts.

This type is declared in WinNT.h as follows:

typedef WCHAR *PWSTR;

A 64-bit unsigned integer.

This type is declared as follows:

typedef unsigned __int64 QWORD;

A handle to a service control manager database. For more information, see SCM Handles.

This type is declared in WinSvc.h as follows:

typedef HANDLE SC_HANDLE;

A lock to a service control manager database. For more information, see SCM Handles.

This type is declared in WinSvc.h as follows:

typedef LPVOID SC_LOCK;

A handle to a service status value. For more information, see SCM Handles.

This type is declared in WinSvc.h as follows:

typedef HANDLE SERVICE_STATUS_HANDLE;

A 16-bit integer. The range is -32768 through 32767 decimal.

This type is declared in WinNT.h as follows:

typedef short SHORT;

The maximum number of bytes to which a pointer can point. Use for a count that must span the full range of a pointer.

This type is declared in BaseTsd.h as follows:

typedef ULONG_PTR SIZE_T;

This type is declared in BaseTsd.h as follows:

typedef LONG_PTR SSIZE_T;

A WCHAR if UNICODE is defined, a CHAR otherwise.

This type is declared in WinNT.h as follows:

A WCHAR if UNICODE is defined, a CHAR otherwise.

This type is declared in WinNT.h as follows:

This type is declared in WinDef.h as follows:

typedef unsigned char UCHAR;

An unsigned HALF_PTR. Use within a structure that contains a pointer and two small fields.

This type is declared in BaseTsd.h as follows:

An unsigned INT. The range is 0 through 4294967295 decimal.

This type is declared in WinDef.h as follows:

typedef unsigned int UINT;

This type is declared in BaseTsd.h as follows:

This type is declared in BaseTsd.h as follows:

typedef unsigned char UINT8;

This type is declared in BaseTsd.h as follows:

typedef unsigned short UINT16;

An unsigned INT32. The range is 0 through 4294967295 decimal.

This type is declared in BaseTsd.h as follows:

typedef unsigned int UINT32;

An unsigned INT64. The range is 0 through 18446744073709551615 decimal.

This type is declared in BaseTsd.h as follows:

typedef usigned __int 64 UINT64;

An unsigned LONG. The range is 0 through 4294967295 decimal.

This type is declared in WinDef.h as follows:

typedef unsigned long ULONG;

A 64-bit unsigned integer. The range is 0 through 18446744073709551615 decimal.

This type is declared in WinNT.h as follows:

This type is declared in BaseTsd.h as follows:

An unsigned LONG32. The range is 0 through 4294967295 decimal.

This type is declared in BaseTsd.h as follows:

typedef unsigned int ULONG32;

An unsigned LONG64. The range is 0 through 18446744073709551615 decimal.

This type is declared in BaseTsd.h as follows:

typedef unsigned __int64 ULONG64;

A Unicode string.

This type is declared in Winternl.h as follows:

An unsigned SHORT. The range is 0 through 65535 decimal.

This type is declared in WinDef.h as follows:

typedef unsigned short USHORT;

An update sequence number (USN).

This type is declared in WinNT.h as follows:

typedef LONGLONG USN;

This type is declared in WinNT.h as follows:

A 16-bit Unicode character. For more information, see Character Sets Used By Fonts.

This type is declared in WinNT.h as follows:

typedef wchar_t WCHAR;

The calling convention for system functions.

This type is declared in WinDef.h as follows:

CALLBACK, WINAPI, and APIENTRY are all used to define functions with the __stdcall calling convention. Most functions in the Windows API are declared using WINAPI. You may wish to use CALLBACK for the callback functions that you implement to help identify the function as a callback function.

Фундаментальные типы данных

Фундаментальными типами для архитектуры IA-32 являются:

байт (byte) - 8 бит
слово (word) - 16 бит
двойное слово (doubleword) - 32 бит
четверное слово (quadword) - 64 бит

При размещении данных в памяти рекомендуется использовать выравнивание, т.е. слова следует размещать по четным адресам, двойные слова - по адресам, кратным четырем, и т.п. Обращение к невыравненным данным вынуждает процессор делать дополнительный цикл чтения или записи. Так, чтение двойного слова AA5A3F12h по адресу 1238h возможно за один цикл шины, тогда как чтение числа 3F12008Ch по адресу 1236h потребует как минимум двух циклов шины.

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

Целые типы данных

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

Фундаментальный тип кодирует беззнаковое число, если его значение интерпретируется как целое число от 0 до 2 n -1, где n - разрядность типа. Для чисел со знаком используется комплементарное кодирование (дополнение до 1): т.е. отрицательному числу, модуль которого M, соответствует код NOT(M)+1, где NOT - операция побитового инвертирования. При этом по старшему разряду кода можно определить знак числа: 0 - неотрицательное число, 1 - отрицательное число. Знаковым числам соответствует диапазон -2 n/2 . +2 n/2 -1.

Фундаментальный типЦелый типДиапазон
байт
(byte)
символ со знаком
(signed char)
-128. +127
символ без знака
(unsigned char)
0. 255
слово
(word)
короткое со знаком
(signed short)
-32768. +32767
короткое без знака
(unsigned short)
0. 65535
двойное слово
(doubleword)
целое со знаком
(signed int)
-2147483648. +2147483647
целое без знака
(unsigned int)
0. 4294967295

Вещественные типы данных

Ближний указатель представляет собой 32-битное смещение (эффективный адрес) от начала сегмента. Ближние указатели используются в сплошной модели памяти, а также в сегментированной модели, если селектор сегмента задан неявно.

Дальний указатель (логический адрес) состоит из 16-битного селектора сегмента и 32-битного смещения (эффективного адреса). Дальние указатели используются в сегментированной модели памяти, когда требуется явное задание селектора сегмента.

В 16-битном режиме адресации смещения имеют размер 16 бит, поэтому размер ближнего адреса составляет 16 бит, а дальнего - 32 бита.

Битовое поле - непрерывная последовательность битов, в которой каждый бит рассматривается как независимая переменная. Оно может начинаться с любого бита любого байта и может быть длиной до 32 бит.

Строка - непрерывная последовательность битов, байтов, слов или двойных слов. Битовая строка может начинаться с любой позиции любого байта и содержать до 2 32 -1 битов. Строка байтов может содержать байты, слова или двойные слова и иметь размер до 2 32 -1 байт.

Двоично-десятичные числа

Пятый день.
О словах и двойных словах
(форматы данных)

Не сказать чтоб эта тема была самая сложная, но то, что она самая запутанная - это 100%.

То, что я здесь напишу, довольно туго для восприятия, однако со временем всё уляжется. Не расстраивайтесь, если вдруг в этой главе покажется, что Ассемблер очень сложный, вспомните о таком фокусе.

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

Примерно такая же информация будет изложена в этой главе. На практике всё быстро усвоится, если вам придется сталкиваться с машинным кодом и данными.

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

Бинарники организуются в отряды по восемь, эти отряды называются байтами. Запомнил?

Байт - это минимальная расчетная единица бинарной армии. Запомнил?

2 байта организуются в слово (word).

4 байта организуются в двойное слово (dword, а пОлно - double word).

Dword - это самый распространённый набор битов в Win32-программах. Так как:

В предыдущей программе мы столкнулись вот с такой строкой:

"d," здесь как раз и заменяет dword.

Я объяснил, что когда операнд находится в квадратных скобках, при команде mov это означает, что нужно производить действие по адресу в памяти, указанному операндом. То есть в BX раньше должен быть положен адрес. В ходе выполнения этой строки BX не изменяется, изменится только память по адресу, указанному BX. Размер изменяемой памяти dword (4 байта, двойное слово).

Остаётся маленький такой вопросик: почему в дизассемблере байты операндов команд процессора мы видим зеркально значениям операндов в командах Асма?

Запомни, матрос, Бинарники очень хитрые. Для того, чтоб их враг путал байты по старшинству, в каждой целой боевой единице, будь то word (2 байта), dword (4 байта), qword (8 байт), байты строятся от младшего к старшему, черт их дери!

Адрес, который был указан в BX, равен 0133h.

А действие выглядит так:

В отладчике вы видели это вот так:

Мы пишем и читаем текст по-европейски - слева направо. Но для чисел большинство людей использует арабскую запись - справа налево (хотя читаем числа тупо от старшей цифры =).

К великому огорчению, программистами был принят смешанный формат отображения данных. Каждый байт отображается по арабской системе, а целая группа байтов - по европейской. Выходит, что на экране мы видим разную запись. Если программа-дизассемблер или отладчик воспринимают группы байтов как ЦЕЛОЕ число, то оно отображается арабской записью, как в колонке команд Ассемблера: 04 03 02 01, а если речь идёт просто о нескольких байтах, то мы видим европейскую запись, только за букву принят целый байт, что и показано выше: 01 02 03 04. Всё это лишь вопрос отображения на экране или в документах. Например, если использовать запись цифровых значений от нижнего правого угла экрана до верхнего левого (справа налево, снизу вверх), то вообще ничего переворачивать не нужно! То есть если бы была принята запись "справа налево всё" или "слева направо всё", то подобных проблем не было бы вообще.

Допустим, мы набрали вот такую строку:

Здесь мы указали, что размер данных word (2 байта) и эти данные будут помещены в память по адресу 800h.

Объясню сейчас коротко.

Раз мы имеем заданный размер word (или как в Hiew'е "w,"), мы имеем некое ЦЕЛОЕ.

Младший байт (у нас AA) будет находиться по наименьшему адресу, а старший байт (BB) - по более старшему адресу.

Вот как эта строка будет выглядеть в Hiew'e:

Вопрос, который наверняка возник у всех (и я предполагаю, что у многих в нецензурной форме): "На. в смысле зачем?"

Это нужно для того, чтобы процессор забирал байты из памяти, начиная с младшего (так быстрее вычислять). Ведь получается, что адрес числовой переменной любого размера, хоть word, хоть dword, будет указывать на младший байт в числе, далее пойдёт следующий байт в числе, и самый старший байт в числе всегда окажется в конце. Вычислять процессору так значительно быстрее.

Всё, из теории остались только циклы и стек, о них мы будем говорить завтра.

Матрос! Я что-то не заметил, чтоб ты разрабатывал кнопку F10!

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

Послезавтра я увижу своё отражение в F10-key у тебя на клавиатуре или я высажу тебя на ближайшей заброшенной планете.

Набивайте всё сами, только так можно научиться.

В Hiew'e она должна выглядеть так:

Но это не всё, теперь переключитесь на Hex-режим (F4) и добейте программу следующими байтами после всего кода. Это будут "данные".

На самом деле все эти пробелы (20h) программе НЕ нужны. Но когда вы будете смотреть программу в отладчике, они вам помогут.

Если у вас будет сдвиг хоть на байт, программа будет ошибочной. Поэтому проверьте, чтобы строка "-=Асм=-$" начиналась с 50h и, что ещё более важно, два нулевых байта (00 00) должны быть в файле по адресам 75 и 76h. Обязательно посмотрите в отладчике, что будет происходить с этими байтами (там они будут 175h и 176h). Всё остальное здесь мишура и для выполнения программы совершенно не имеет значения.

Результат действия этой программы - вывод строк по диагонали от верхнего левого угла до нижнего правого угла.

Здесь очень много нового, и я надеюсь, вам будет интересно узнать, как работают новые команды CMP и JNE.

Попробуйте сами разобраться, что происходит в программе на практике. Как я уже писал, прерываний (команда int) при написании программ Win32 мы использовать не будем. Поэтому можете не заострять на них внимание. Достаточно знать, что это полезные подпрограммы, часть которых заложена ещё в BIOS (basic input/output system - базовая система ввода/вывода).

Я вынужден их использовать только для того, чтобы программа была полноценная и вы могли наглядно изучать главные команды Ассемблера.

В данном примере будут задействованы int 10h для очистки экрана (AL=3) и для расположения курсора текста (AH=2). Ну и int 21h для вывода текста на экран. Всё, других прерываний в уроках больше не будет. О них за долгие годы написано достаточно.

Вот как программа должна трактоваться (сразу скажу - про метки я всё объясню позже).

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

Я пытаюсь понять, почему значение DWORD часто описывается в шестнадцатеричном формате на MSDN.

причина, по которой я анализирую это, заключается в том, что я пытаюсь понять фундаментально, почему существуют все эти различные типы данных чисел. Местный наставник намекнул мне, что создание DWORD и других типов Microsoft имеет какое-то отношение к эволюции процессоров. Это придает смысл и контекст моему пониманию этих типов данных. Я хотел бы больше контекста и фон.

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

вкратце, мои вопросы: 1) Почему DWORDs представлены в Hex? 2) Можете ли вы выделять различия между числовыми типами данных, и почему они были созданы?

все в компьютере-это куча нулей и единиц. Но писать целый DWORD в двоичном формате довольно утомительно:

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

обычная стенография для определения того, какая база используется:

Что касается вашего вопроса о BYTE, WORD, DWORD и т. д.

компьютеры начали с немного. Только 1 или 0. У него была камея в оригинальном троне.

затем компьютеры выросли до 16-битных регистров. Это 2 байта и стало известно как слово (Нет, я не знаю, почему). Теперь числа могут быть от 0-65535 или от -32768 до 32767.

мы продолжали хотеть больше силы, и компьютеры были расширены до 32-разрядных регистров. 4 байта, 2 слова, также известный как DWORD (двойное слово). И по сей день ты можешь заглядывать". C:\Windows "и см. каталог для" системы "(старые 16-битные части) и" system32 " (новые 32-битные компоненты).

затем появилось QWORD (quad-word). 4 слова, 8 байт, 64 бита. Когда-нибудь слышали о Nintendo-64? Вот откуда взялось это имя. Современная архитектура теперь здесь. Внутренние части процессора содержат 64-разрядные регистры. Обычно вы можете запустить 32-или 64-разрядная операционная система на таких процессорах.

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

Я не покрывал числа с плавающей запятой, но, надеюсь, это поможет с общей идеей.

константы DWORD обычно записываются в hex, когда они используются в качестве флагов, которые могут быть или вместе побитовым способом. Это облегчает понимание того, что это так. Вот почему вы видите 0x01, 0x02, 0x04, 0x08, 0x10, 0x20 и т. д. Программисты просто распознают эти значения как двоичные представления с одним битовым набором.

когда это перечисление, вы увидите 0x01, 0x02,0x03 и т. д. Они часто все еще написаны на hex, потому что программисты склонны к этим привычкам!

только для записи 16-битные неподписанные данные называются WORD beacause в то время, компьютеры имели 16-битные регистры.

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

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

Итак, на некоторых компьютерах использование другого слова CPU обычно относится к размеру регистра. На Saturn CPU, который использует 64-битный регистр, слово составляет 64 бита.

когда 32-битные процессоры x86 вышли, WORD остался 16 бит по соображениям совместимости, и DWORD был создан, чтобы расширить его до 32 бит. То же самое верно для qword и 64 бит.

А почему шестнадцатеричное широко используется чтобы описать слово, оно должно иметь отношение к природе определения слова, которое привязано к его регистровому происхождению. В ассемблерном программировании вы используете шестнадцатеричное для описания данных, потому что процессоры знают только binray intergers (0 и 1). И шестнадцатеричный-это более компактный способ использования двоичного кода и сохранения некоторых его свойств.

чтобы уточнить ответ Тима, это потому, что преобразование Hex в двоичный и обратно очень легко - каждая шестнадцатеричная цифра составляет 4 двоичных цифры:

и 0x2D = 0010 1101

у Вас очень интересный и каверзный вопрос.

короче говоря, было два драйвера, которые приводят к существованию семейств конкурирующих типов-DWORD-based и int-based:

1) Желание иметь crosspltformity с одной стороны и stricktly типы размера с другой стороны.

2) консерватизм народов.

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

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

С другой стороны, в то же время с каждым годом языки высокого уровня становились все более популярными. И потому, что languges был разработан с кросс-платформенным приложением в уме thay посмотрел на размеры своих внутренних типов данных с совершенно другой точки зрения. Если я правильно понимаю ни один язык высокого уровня четко не утверждает, что некоторые из его внутренних типов данных имеют фиксированный постоянный размер, который никогда не будет изменен в будущем. Давайте не смотреть на C++ как на примере. Стандарт C++ говорит, что:

Итак, мы видим удивительную информацию-в C++ даже байт не имеет постоянного размера. Так что даже если мы привыкли считать, имеют размер 8 бит, по данным C++ может быть не только 8 но и 9, 10, 11, 12 и т. д. биты по размеру. И, может быть, даже 7 бит.

это цитирует описание двух основных утверждений:

1) оператор sizeof(тип char)

2) простые Инты имеют естественный размер, предложенный архитектурой среды выполнения. Это означает, что int должен иметь размер машинного слова архитектуры целевого процессора.

вы можете пройти через весь стандартный текст C++, но вы не сможете найти что-то вроде " размер int равен 4 байт" или "длина 64 бит". Размер отдельных целочисленных типов C++ может изменяться при переходе от одной архитектуры процессора к другой и при переходе от одного компилятора к другому. Но даже когда вы пишете программу на c++, вы периодически сталкиваетесь с необходимостью использовать типы данных с известным постоянным размером.

по крайней мере, более ранние разработчики компиляторов следовали этим стандартным утверждениям. Но теперь мы видим, что консерватизм людей входит в игру еще раз. Люди раньше считалось, что int 32-разрядный и может хранить значения из диапазона от -2,147,483,648 до 2,147,483,647. Раньше, когда промышленность проходила границу между 16-битной и 32-битной архитектурой. Второе требование было строго исполнено. И когда вы использовали C++ компилятор для создания 16-разрядных программ, компилятор использовать тип int 16-битный размер, ЧТО ТАКОЕ "натуральный размер" для 16-разрядных процессоров и, напротив, когда ты использовал другой компилятор C++ для создания 32-разрядных программ, но из того же исходного кода, компилятор использовать тип int с 32-битной размер "натурального размера" для 32-разрядных процессоров. В настоящее время, если вы посмотрите, например, на компилятор Microsoft c++, вы обнаружите, что он будет использовать 32-разрядный int независимо от архитектуры целевого процессора (32-разрядный или 64-разрядный) только потому, что люди привыкли думать, что int 32-разрядный!

как summury, мы можем видеть, что thare - это два семейства типов данных - на основе dword и int. Мотивация для второго очевидна-кросс-платформенная разработка приложений. Мотивация для fisrt - это все случаи, когда учет размеров переменных имеет смысл. Например, среди прочих можно упомянуть следующие случаи:

1) вам нужно иметь некоторое значение в предопределенном хорошо известном диапазоне, и вам нужно использовать его класс или в другой структуре данных, которая будет заполняться огромным количеством экземпляров во время выполнения. В этом случае, если вы будете использовать типы на основе int для хранения этого значения, это будет иметь недостаток в огромных накладных расходах памяти на некоторых архитектурах и потенциально может сломать логику на другом. Например вам нужно манипулировать значениями в диапазоне от 0 до 1000000. Если вы используете int для ее хранения, то программа будет правильно себя вести, если int будет 32-битный, будет 4 байта памяти для каждого значения если int будет 64-битным, и он не будет работать правильно, если инт будет 16-битным.

2) Данные, участвующие в nextworking. Чтобы иметь возможность правильно обрабатывать сетевой протокол на разных ПК, вам понадобится чтобы указать его в простом формате на основе размера, который будет описывать все пакеты и заголовок бит за битом. Ваша сетевая связь будет полностью нарушена, если на одном ПК заголовок протокола будет иметь длину 20 байт с 32-битным, а на другом ПК-длину 28 байт с 64-битным int.

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

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

5) Ваш алгоритм полагается на логику переполнения целого числа. Например, у вас есть массив из 2^16 записей, и вы хотите infenitely и sequentely идет через него, и значения записей обновления. Если вы будете использовать 16-битный int, ваша программа будет работать отлично, но wimmediatelly вы переходите к 32-битному использованию int, у вас будет доступ к индексу массива вне диапазона.

из-за этого Microsoft использует оба семейства типов данных. Типы на основе Int в случае, когда фактический размер данных не имеет большого значения, и DWORD-в случаях, когда он имеет. И даже в этом случае Microsoft определить как макросы, чтобы обеспечить возможность быстро и достаточно легко принять систему виртуального типа, используемую Microsoft для конкретной архитектуры процессора и/или компилятора, назначив ему правильный эквивалент c++.

Я надеюсь, что я достаточно хорошо рассмотрел вопрос о происхождении типов данных и их различиях.

Итак, мы можем перейти к вопросу seqond о том, почему шестнадцатеричная цифра используется для обозначения значений типов данных на основе DWORD. На самом деле их немного причины:

1) Если мы используем двоичные типы данных stricktly-sized, это будет достаточно очевидно, что мы можем захотеть посмотреть на них в двоичной форме.

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

тогда, если он будет закодирован в следующей форме

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

это свойство двоичного кодирования очень привлекательно в том случае, когда требуется анализ огромного количества двоичных данных. Например, редактор hex или анализ простой памяти используется программой в отладчике при попадании в точку останова. Согласитесь, что гораздо удобнее смотреть на аккуратные столбцы значений, которые к куче слабо выровненных значений размера переменной.

Итак, мы решили, что хотим использовать двоичное кодирование. У нас есть три варианта: использовать обычное двоичное кодирование, восьмеричное кодирование и шестнадцатеричное кодирование. Peple предпочитает использовать шестнадцатеричное кодирование, потому что оно наиболее короткое из набора доступных кодировок. Просто сравнить

можете ли вы быстро найти числа битов, которые установлены в следующем значении?

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

в каждом из которых первая цифра обозначает 4 наиболее значимых бита, а вторая - еще 4 наименее значимых бита. После того, как вы потратите некоторое время на работу с hex значения вы запомните простой битовый аналог каждой шестнадцатеричной цифры и без проблем замените одно на другое в уме:

Итак, нам нужно всего секунду или две, чтобы обнаружить, что у нас установлен бит номер 20!

люди используют hex, потому что он самый короткий, удобный для undestand и использовать форму двоичного кодирования данных.

Читайте также: