Представление переменных в памяти (порядок байт)

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Представление переменных в памяти (порядок байт)

Сообщение Kitayets » 04.04.2013 15:51:32

на стороннем форуме решали задачу - как получить и вывести бинарное представление в памяти переменной типа Real.
и обратную задачу - есть строка с бинарным представлением неких данных - привести их к типу Real и присвоить соответствующей переменной.

вроде всё просто - тип Real имеет размер 8 байт, в rtl есть функция binStr - которая умеет возвращать строку в бинарном формате представления для qword, longint, int64. Объявляем указатель на Qword (размер QWord очевидно тоже 8 байт) приводим указатель на изначальную переменную к указателю на Qword и печатаем содержимое памяти - всё ок по первой задаче.
Вторая задача - берём полученную строку, преобразуем по 8 символов в байт и записываем в массив из 8 байтов и через указатель присваиваем содержимое всего массива в переменную типа Real.

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

Почему так? где я ошибся?

вот программа - !!!! отмечена строка с записью байтов в массив:
Код: Выделить всё
program real_dump2;
{$mode objfpc}{$H+}
uses
  sysutils;
type
  PReal = ^Real;
var
  value:  Real;
  pValue: PReal;
  rawVal: PQWord;
  binData: packed array[0..7] of byte; // восьмибайтовый массив
  //двуичное представление числа, которое мы хотим преобразовать в Real
  binDataStr2: String = '01000000' +
                        '01011000' +
                        '11010010' +
                        '00111101' +
                        '01110000' +
                        '10100011' +
                        '11010111' +
                        '00001010';
  i: Integer;
  //функция на входе принимает строку с бинарным предствалением одного байта
  //(8 бит), кждый символ который соотвествует 0 или 1
  //и преобразует в тип Byte
  function binStrToByte(const aStr: string): byte;
  var
    i: integer;
  begin
    result:=0;
    Assert((Length(aStr) > 1) and (Length(aStr) <= 8),'Wrong number of bits!');
    for i:=1 to Length(aStr) do begin
      Result:= Result shl 1;
      Assert(StrToInt(aStr[i]) < 2, 'Not a bynary format!');
      Result:= Result or byte(StrToInt(aStr[i]));
    end;
  end;

begin
  // из типа Real  в бинарное представления содиржимого памяти
  value:= 99.285;
  rawVal:= PQWord(@value);
  writeln('value = ', value);
  //тут значение каждого бита
  writeln('memory dump in binary format: ', char(#10) ,binStr(rawVal^, sizeof(QWord)* 8));
  //каждый байт в виде шестнациричного значения от 00 (0) до FF (255)
  //т.е. это не одно число а 8 шестнациричных чисел
  writeln('memory dump in hexadecimal format : ',HexStr(rawVal^, sizeof(QWord)* 2));

  //из бинарного представления в тип Real
  writeln;
  Writeln('src string: ', char(#10), binDataStr2);
  //записываем бинарное представление в массив из 8-ми байт
  for i:=0 to 7 do
    binData[7 - i]:= binStrToByte(Copy(binDataStr2, i*8 +1, 8));  {!!!!}
  pValue:=PReal(Addr(binData));
  //выводим что получилось
  value:= pValue^;
  writeln('value = ',Value);
  readln;
end.
Kitayets
постоялец
 
Сообщения: 171
Зарегистрирован: 05.05.2010 21:15:24

Re: Представление переменных в памяти (порядок байт)

Сообщение bormant » 04.04.2013 16:53:05

Kitayets писал(а):Почему так?

http://ru.wikipedia.org/wiki/%D0%9F%D0% ... 0%BE%D0%B2
Архитектуры x86/x86_64 -- little endian, то есть значение $1122334455667788 побайтово хранится в памяти так: $88, $77, $66, $55, $44, $33, $22, $11.
Kitayets писал(а):где я ошибся?
Здесь:
Kitayets писал(а):приводим указатель на изначальную переменную к указателю на Qword и печатаем содержимое памяти
Вы печатаете не содержимое памяти, а значение QWord, которое на little endian системах хранится от младшего байта к старшему. То есть, в вашем выводе получается
for i:=7 downto 0 do s := s+BinStr(Byte((PChar(указатель)+i)^));
а в памяти оно лежит как
for i:=0 to 7 do s := s+BinStr(Byte((PChar(указатель)+i)^));
Аватара пользователя
bormant
постоялец
 
Сообщения: 408
Зарегистрирован: 21.03.2012 11:26:01

Re: Представление переменных в памяти (порядок байт)

Сообщение Kitayets » 05.04.2013 11:39:06

Теперь всё встало на свои места. Спасибо за развёрнутый ответ.
Kitayets
постоялец
 
Сообщения: 171
Зарегистрирован: 05.05.2010 21:15:24


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru
cron