Difference between revisions of "Writing portable code regarding the processor architecture/ru"

From Lazarus wiki
Jump to navigationJump to search
Line 180: Line 180:
  
 
{{AutoCategory}}
 
{{AutoCategory}}
[[Category:Russian (unfinished translation)]]
 
 
[[Category:Data types/ru]]
 
[[Category:Data types/ru]]
 
[[Category:Processors/ru]]
 
[[Category:Processors/ru]]

Revision as of 13:58, 11 October 2015

English (en) Bahasa Indonesia (id) русский (ru)

Существует ряд проблем связанных с написанием кода, являющегося не зависимым от процессорной архитектуры. Одна из них - это порядок следования байтов, другая – разрядность процессора (32 или 64-битные ЦП).

Порядок следования байтов (ПСБ)

Порядок следования байтов определяет, как будет хранить ЦП значения больше одного байта. (т.е. 16/32/64-битные целые числа).

Free Pascal поддерживает процессоры с двумя типами следования байтов:

  1. Порядок следования от младшего к старшему байту: longint(4) кодируется как 04 00 00 00 (little endian)
  2. Порядок следования от старшего к младшему байту: longint(4) кодируется как 00 00 00 04 (big endian)

Примечание:

Процессоры со средним(смешаным) порядком байтов, известный так же, как смешанный порядок байтов, сегодня встречаются редко. Наиболее известный представитель процессоров со смешанным порядком байтов является устаревший сегодня PDP-11 производства компании DEC.

Каждое семейство процессоров имеют свой порядок байтов, но как правило они либо от младшего к старшему, либо от старшего к младшему, в зависимости от архитектуры (ARM, PPC).

Самые известные представители процессоров с порядком следования байтов от младшего к старшему, являются процессоры семейства x86, используемые в ПК, и его собратья x86-64. Типичными же представителями процессоров с порядком следования байтов от старшего к младшему являются процессоры семейства PPC (см. примечание выше) и процессоры m68k, использовавшихся в миникомпьютерах HP3000, а так же в майнфреймах подобные IBM 370 (серия Z).

Поскольку спецификация TCP/IP предполагает, что все заголовки в структуре протокола должны храниться с порядком байтов от старшего к младшему, то данный порядок байтов иногда упоминается как «сетевой порядок следования байтов».

Наиболее важен порядок байтов в следующих случаях:

  1. при обмене данными компьютерами с различными архитектурами ЦП
  2. при доступе к большому количеству данных, например, представленных в виде массива целых чисел или байтов.


Пример последнего:

type
  Q = record
    case Boolean of
      True: (i: Integer);
      False: (p: array[1..4] of Byte);
  end;
 
var 
  x:^Q;
 
begin
  // Указываем компилятору порядок следования байтов(ПСБ):
  {$IFDEF ENDIAN_LITTLE}
  Writeln('Программа скомпилирована для компьютеров с ПСБ от младшего к старшему (например Intel x86, ARMEL)');
  {$ENDIF}
  {$IFDEF ENDIAN_BIG}
  Writeln('Программа скомпилирована для компьютеров с ПСБ от старшего к младшему (например PowerPC, ARMEB)');
  {$ENDIF}  
  New(x);
  x^.i := 5;
  if x^.p[1] = 5 then
    WriteLn(x^.p[1],' На вашей машине ПСБ от младшего к старшему')
  else
  if x^.p[4] = 5 then
    WriteLn(x^.p[1],' На вашей машине ПСБ от старшего к младшему')
  else
    WriteLn(x^.p[1],' ',x^.p[2],' ',x^.p[3],' ',x^.p[4],' Порядок следования байтов не определён');  
  WriteLn;
 
  { Сделаем паузу для просмотра результата }
 
  Write('Нажмите Enter для выхода из программы ');
  ReadLn;
end.

Данный пример на компьютерах с ПСБ от младшего к старшему выведет число 5 (т.к. число 5 хранится в памяти в виде 05 00 00 00). В то же время, компьютеры с ПСБ от старшего к младшему (например, PowerMac) выведут 0 (поскольку число 5 хранится в памяти в виде 00 00 00 05).

Для определения порядка следования байтов, служат директивы компилятора ENDIAN_BIG и ENDIAN_LITTLE (или FPC_LITTLE_ENDIAN и FPC_BIG_ENDIAN начиная с версии 1.9).

Изменение ПСБ

Модуль system имеет ряд процедур для преобразования данных между порядком следования байтов от старшего к младшему и ЦП, на которым выполняется программа (BEtoN, NtoBE). Соответствующие процедуры реализованы и для машин с ПСБ от младшего к старшему: LEtoN, NtoLE. Имеются также процедуры для смешанного порядка байтов (SwapEndian).

Некоторые сетевые библиотеки, например Synapse имеют собственные реализации конвертации ПСБ между сетью и компьютером.

Согласование

Некоторые процессоры могут не правильно выстроить данные в памяти. Это может привести к изменению размера типа данных запись(record), поэтому всегда используйте функцию sizeof для проверки размера записи.

32 Bit и 64 Bit

Для достижения максимальной совместимости со старым кодом, FPC не изменяет размер стандартных типов данных, например: integer, longint или word при переходе с 32 разрядного на 64-ёх разрядный ЦП. Выражения, вроде longint(pointer(p)) приведут к ошибке на 64-разрядных процессорах. Для написания переносимого кода в FPC введены типы PtrInt и PtrUInt в модуле system, представляющие собой знаковые и беззнаковые целочисленные типы данных такого же размера, как и указатель(Pointer).

Имейте в виду, что смена размера типа "pointer" так же влияет на размер записей, если Вы определите запись не фиксированного размера, а через процедуры new или getmem (<x>,sizeof(<x>)).

Это относится к открытым платформам Unix. В коммерческом мире, существуют некоторые исключения, например Tru64 или ILP64.

Согласование вызовов

В общем, случаи, старайтесь не полагаться на собственные знания. Лучше воспользуйтесь следующей таблицей:

Ключевое слово ПСБ Стек очищает Выравнивание Регистры сохранены?
нет с лева на право функция по умолчанию нет
Register с лева на право функция по умолчанию нет
CDecl с право налево вызывающий GCC выравнивание только GCC регистры
Interrupt с право налево функция по умолчанию да
Pascal с лева на право функция по умолчанию нет
SafeCall с право налево функция по умолчанию только GCC регистры
StdCall с право налево функция GCC выравнивание только GCC регистры
OldFPCCall с право налево вызывающий по умолчанию нет

Более подробная информация: $CALLING.

Ограничения, по размеру параметров, для различных архитектур ЦП:

Архитектура ЦП Размер параметров Размер локальных переменных
i386 64 КБ нет лимита
AMD64/x86-64 64 КБ нет лимита
Motorola 68000 32 КБ 32 КБ
Motorola 68020 32 КБ нет лимита
PPC нет лимита нет лимита
ARM нет лимита нет лимита
SPARC нет лимита нет лимита

Мэйнфреймы

Для архитектур IBM 370 и Z - серии, смотрите подробности здесь.

x86

В процессорах x86, все параметры, обычно, передаются через стек, однако, если функция вызывается в режиме совместимости с Delphi, то первые три параметра или параметры, имеющие один адрес, передаются через регистры EAX, EDX и ECX. Исключением из данного правила, может являться процесс разработки ПО для ОС Darwin и Mac OS X.

ARM

PPC

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

Процессоры PowerPC, так же используют стандарты AIX или SysV при вызовах функций. Смотрите подробнее здесь.

68K

Процессоры 68K поддерживают CDecl и Pascal согласование вызовов. Более подробную информацию, смотрите тут: 68K vs. PowerPC.

Стек, после вызова процедуры или функции на этих ЦП, выглядит примерно так:

возвращаемое значение
первый параметр
...
последний параметр
статические ссылки (опционально)
адрес возврата
A6 предыдущие A6
локальные переменные
SP сохраненные регистры

Ссылки по данной теме


navigation bar: data types
simple data types

boolean byte cardinal char currency double dword extended int8 int16 int32 int64 integer longint real shortint single smallint pointer qword word

complex data types

array class object record set string shortstring