asm записать регистр в переменную?

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

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

Ответить
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

asm записать регистр в переменную?

Сообщение zub »

была функция:

Код: Выделить всё

function mynow:TMyTimeStamp;
var a:int64;
begin
     result.time:=now();
     asm
        rdtsc
        mov [a],eax //тут стал ругаться
        mov [a+4],edx //тут стал ругаться
     end;
     result.rdtsc:=a;
end;

вроде работала, сегодня обновил FPC до 17096 - заругался

Код: Выделить всё

log.pas(158,17) Error: Asm: 64 Bit operands not supported
log.pas(159,19) Error: Asm: 64 Bit operands not supported

как поправить? (хотя вроде всё правильно :lol: )
XP, LAZARUS SVN 29766, FPC SVN 17096
Maxizar
постоялец
Сообщения: 385
Зарегистрирован: 20.03.2010 18:48:14

Сообщение Maxizar »

А так:

Код: Выделить всё

procedure Time1(var a:Int64); assembler; register;
{$ASMMODE intel}
asm
mov ecx,a
rdtsc
mov [ecx],eax
mov [ecx+4],edx
end;
function RDTSC: Int64; register;
begin
  {$ASMMODE intel}
  asm
    rdtsc
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var a:Int64;
begin
  a:=0;
  Time1(a);
  Caption:=IntToStr(a);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
   Caption:=IntToStr(RDTSC);
end;   


У меня вроде работает.. но на старом декабарьском лазарусе...
Кстати в догонку тоже спрошу... везде пишут что:
RDTSC (Read Time-Stamp Counter, opcode: 0F 31). При выполнении этой инструкции 64-битная величина TSC, соответствующая текущему состоянию счетчика, помещается в два 32-битных регистра EDX:EAX (EDX содержит биты старшего разряда TSC)
тогда почему мы пишем так:

Код: Выделить всё

procedure Time1(var a:Int64); assembler; register;
{$ASMMODE intel}
asm
mov ecx,a
rdtsc
mov [ecx],eax
mov [ecx+4],edx
end;

ведь [ecx] - содержит указатель на начало 64 битного числа тобишь, на старшие 64..33 бита? а [ecx+4] на оставшиеся младшие 32...1 биты.. ? или нет?
Т.е должны были писать так:

Код: Выделить всё

procedure Time1(var a:Int64); assembler; register;
{$ASMMODE intel}
asm
mov ecx,a
rdtsc
mov [ecx],eDx
mov [ecx+4],eAx
end;
Последний раз редактировалось Maxizar 09.03.2011 22:23:25, всего редактировалось 1 раз.
Аватара пользователя
coyot.rush
постоялец
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48

Сообщение coyot.rush »

rdtsc http://delphiworld.narod.ru/base/rdtsc.html

Код: Выделить всё

function RDTSC: comp;
var
  TimeStamp: record
    case byte of
      1: (Whole: comp);
      2: (Lo, Hi: Longint);
  end;
begin
  asm
    db $0F; db $31;
  {$ifdef Cpu386}
    mov [TimeStamp.Lo], eax
    mov [TimeStamp.Hi], edx
  {$else}
    db D32
    mov word ptr TimeStamp.Lo, AX
    db D32
    mov word ptr TimeStamp.Hi, DX
  {$endif}
  end;
  Result := TimeStamp.Whole;
end;

PS: тема RDTSC на форуме обсуждалась не раз
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Maxizar
>>на старшие 64..33 бита? а [ecx+4] на оставшиеся младшие 32...1 биты.. ?
насколько помню наоборот

coyot.rush
Вопрос не про рдтсц, а про почему компилятор вдруг стал считать что адрес у 64битной переменной тоже 64битный?

Код: Выделить всё

TimeStamp: record

почему не packed record?
Maxizar
постоялец
Сообщения: 385
Зарегистрирован: 20.03.2010 18:48:14

Сообщение Maxizar »

zub писал(а):насколько помню наоборот

Да я понимаю что наоборот... вопрос почему так было сделано, ведь не логично как то.
Вот скажем у нас есть две ячейки памяти по 4 байта. я1 и я2.
скажем есть такие переменные как:

Код: Выделить всё

var a,b:Integer;
      c  : Int64;

Так вот когда мы пишем так:

То да мы ссылаемся скажем на ячейку я1, в которое влезло все число.
а когда

Если предположить что число записано так: я1я2.
То указатель P будет указывать на я1. Но в я1 будут младшие биты (32..1)..
а P+4 будет указывать на ячейку я2, в которой записаны старшие биты...
Зачем мы как бы перевернули 2 части (по 32 бита) большого числа Int64?... У нас в памяти число записано так по битам: я1(32..1)я2(64..33).
Кто мне объяснит зачем?, в чем фишка.
Спасибо.
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Maxizar писал(а):Кто мне объяснит зачем?, в чем фишка.

Некоторые знания можно почерпнуть отсюда http://ru.wikipedia.org/w/index.php?title=%D0%9F%D0%BE%D1%80%D1%8F%D0%B4%D0%BE%D0%BA_%D0%B1%D0%B0%D0%B9%D1%82%D0%BE%D0%B2&oldid=32408097.
Maxizar
постоялец
Сообщения: 385
Зарегистрирован: 20.03.2010 18:48:14

Сообщение Maxizar »

Да то что доктор прописал.. Спасибо Вам Mr.Smart
Я даже доку сохронил на всякий случай... вдруг решат что данная страница вики не нужна.
Я в посту выше даже ошибся число типа Int64 записывается для интел по типу: от младшего к старшему... тобишь я1(1..32)я2(33..64) Это кстати показал дамп памяти в делфи при отладке... я записывал число 2 в переменную типа Int64. так вот память выглядит таким вот образом:

Код: Выделить всё

02 00 00 00 00 00 00 00
т.е. как и написано в доке...

Еще раз спасибо, я сегодня стал немного умнее :)

PS. Надеюсь в лазарусе когда нибудь появится дамп памяти и значение регистров в hex, где то такую мысль я уже слышал :) Очень бы помогло, особенно при изучении assembler.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

zub писал(а):Вопрос не про рдтсц, а про почему компилятор вдруг стал считать что адрес у 64битной переменной тоже 64битный?


Не адрес, а сама переменная "a" объявлена как int64. Раньше компилятор не обращал на это внимание, теперь исправили.
Ответить