Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.10.30;
Скачать: [xml.tar.bz2];

Вниз

Непонятки с адресацией   Найти похожие ветки 

 
DMitryFox   (2005-08-24 15:31) [0]

Люди подскажите, почему может не работать нижеследующий код и как можно исправить ситуацию:

 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
 private
   ptest: pointer;
 end;

.....

procedure TForm1.FormCreate(Sender: TObject);
begin
 ptest := VirtualAlloc(0, $100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 asm
         xorps   xmm0, xmm0
         mov     [eax], ptest
         movapd  [eax], xmm0 // ERROR !!! Access Violation!!!
 end;
end;


Причем, если  
ptest := VirtualAlloc.....
Перенести в процедуру Button1Click, то все работает нормально.
Иными словами, мне необходимо при создании объекта навыделять памяти через VirtualAlloc для дальнейшего использования в разных методах...

Спасибо


 
begin...end ©   (2005-08-24 15:38) [1]

> DMitryFox   (24.08.05 15:31)

> mov     [eax], ptest

Поясните это. Разве перед выполнением этой строки содержимое EAX не равно нулю?


 
DMitryFox   (2005-08-24 15:39) [2]

сорри еах без скобок, но всерно не работает
mov    eax, ptest


 
Digitman ©   (2005-08-24 15:40) [3]


> мне необходимо .. навыделять памяти через
> VirtualAlloc


чем тебе GetMem не угодил ?
что за велосипед ?


 
DMitryFox   (2005-08-24 15:50) [4]

getmem не подходит для использования с SSE,т.к. возвращает не выровненные 16 значения адресов...


 
DMitryFox   (2005-08-24 15:55) [5]

Пофигу, с GetMem всерно не пашет, даже без использования SEE
 asm
         mov     eax, ptest
         mov      [eax], ebx // Access Violation...
 end;


Посмотрел как делает компилятор, если прописать:

 asm
        mov     eax, [ebp-$04]
        mov     eax, [eax + ptest]
        xorps   xmm0, xmm0
        movapd  [eax], xmm0
 end;

Может кто-нибуть пояснить, плиз ?


 
Digitman ©   (2005-08-24 15:56) [6]


> не выровненные 16 значения адресов


эт чего такое ? что за галиматья ?

говори по-русски - выравнивание на границу "слова" КАКОЙ разрядности тебе нужно ? 32 ? 64 ?


 
Digitman ©   (2005-08-24 16:17) [7]

особо радует перемещение сабжа в "WinAPI" - именно в WinAPI и следует искать ответ на вопрос.


 
DMitryFox   (2005-08-24 16:24) [8]


> эт чего такое ? что за галиматья ?
>
> говори по-русски - выравнивание на границу "слова" КАКОЙ
> разрядности тебе нужно ? 32 ? 64 ?

{$ALIGN 16} нужен.
но в D7 такого нет...


 
Digitman ©   (2005-08-24 16:30) [9]


> {$ALIGN 16} нужен


не надо цитировать "умные слова" !

выравнивание на границу слова КАКОЙ разрядности тебе требуется ?!


 
Игорь Шевченко ©   (2005-08-24 16:33) [10]


> Может кто-нибуть пояснить, плиз ?


Конечно может. Этот "кто-то" называется отладчик.


 
DMitryFox   (2005-08-24 16:34) [11]

I>
> выравнивание на границу слова КАКОЙ разрядности тебе требуется
> ?!

SSE требует для работы выравнивание данных на 16 байт - что тут непонятного...


 
alpet ©   (2005-08-24 16:48) [12]

DMitryFox   (24.08.05 16:34) [11]

Попробуй посмотреть в Watch какое значение получается в регистре eax,  и насколько оно отличается от ptest.

procedure TForm1.Set1;
asm
mov       eax, [self.ptest]
mov       dword ptr [eax], 1
end;


 
Digitman ©   (2005-08-24 16:48) [13]

не вижу проблем.

- выдели с пом. GetMem() блок памяти размером не меньшим чем (n + 1) * 16байт

- для полученного адреса предоставленного тебе менеджером памяти блока расчитай/найди первый же адрес кратный 16-ти


 
alpet ©   (2005-08-24 16:50) [14]

Кстати - при использовании VirtualAlloc нет смысла выделять меньше страницы памяти (4Кбайт).


 
DMitryFox   (2005-08-24 16:52) [15]


> не вижу проблем.
>
> - выдели с пом. GetMem() блок памяти размером не меньшим
> чем (n + 1) * 16байт
>
> - для полученного адреса предоставленного тебе менеджером
> памяти блока расчитай/найди первый же адрес кратный 16-ти

Нафига мне это делать, если я могу спокойно пользоваться VirtualAlloc ? что и делаю... вопрос в другом, см первый пост.
Почему я из асма в другом методе не могу достучаться напрямую до указателя ?


 
DMitryFox   (2005-08-24 16:54) [16]


> Конечно может. Этот "кто-то" называется отладчик.

Он может ответить на вопрос, почему вместо одной команды
mov eax, ptestя должен использовать наворот
mov eax, [bp - 4]
mov eax, [eax + ptest]

что за адрес содержится в ptest ?
что лежит на стеке-4 ?


 
alpet ©   (2005-08-24 16:58) [17]

DMitryFox   (24.08.05 16:52) [15]

program temp;
uses Windows;
type TClass1 = class
public
ptest: Pointer;
constructor Create;
destructor Destroy; override;
procedure  Test;
end;

{ TClass1 }

constructor TClass1.Create;
begin
ptest := VirtualAlloc (nil, 4096, MEM_COMMIT, PAGE_READWRITE);
end;

destructor TClass1.Destroy;
begin
VirtualFree (ptest, 4096, MEM_DECOMMIT);
end;

procedure TClass1.Test;
asm
push      ebx
push      edx
mov       ebx, ptest
mov       edx, [ptest] ; cause av
mov       eax, [self.ptest] ; yes is right!
test      eax, eax
pop       edx
pop       ebx
end;

var c: TClass1;
begin
c := TClass1.Create;
c.Test;
c.Free;
end.


Compiler results:

mov  ebx, ptest
mov  ebx, $00000004
mov edx, [ptest] ; cause av
mov  edx, [$00000004]
mov eax, [self.ptest] ; yes is right!
mov  eax, [eax + $00000004]
....


 
Digitman ©   (2005-08-24 17:20) [18]


> Нафига мне это делать, если я могу спокойно пользоваться
> VirtualAlloc ?


нафига тебе VirtualAlloc, если ты тоже самое можешь реализовать НЕ выходя за рамки ОР ?

если ты НЕ в состоянии расчитать требуемые в дан.случае для GetMem()параметры, то нехрена тебе делать в WinAPI.


 
icWasya ©   (2005-08-24 17:23) [19]

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

Скорее всего везде, где есть обращение к полям TForm1 нужно вместо


asm
   ...
    mov     eax, ptest
   ...
end;

писать

asm
   ...
    mov     ebx, self
    mov     eax, TForm1([ebx]).ptest; //  что бы точно понимать, что же мы делаем
   ...
end;


Кроме того, надо помнить, что по умолчанию несколько параметров передаются через регистры. В данном случае
procedure TForm1.Button1Click(Sender: TObject);
- метод с одним параметром - Self=EAX, Sender=EDX;
При входе в процедуру скорее всего эти  регистры будут сохранены, но оптимизатор может думать по другому - если не найдёт явного использования Self, то EAX сохраняться не будет, и придётся это делать самому, например, используя не ячейку в стеке, а какой нибудь регистр.


procedure TForm1.Button1Click(Sender: TObject);
asm
   mov ebx,eax; // сохраняем

   xorps   xmm0, xmm0
   //mov     [eax], ptest
    mov     eax, TForm1([ebx]).ptest;

    movapd  [eax], xmm0 //
end;


 
DMitryFox   (2005-08-24 17:23) [20]


> procedure TClass1.Test;
> asm
> push      ebx
> push      edx
> mov       ebx, ptest
> mov       edx, [ptest] ; cause av
> mov       eax, [self.ptest] ; yes is right!
> test      eax, eax
> pop       edx
> pop       ebx
> end;

Работает - все круто.
пробую:
procedure TForm1.FormCreate(Sender: TObject);
begin
 ptest := VirtualAlloc(0, $100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 asm
         mov     ecx, self.ptest
         xorps   xmm0, xmm0
         movapd  [ecx], xmm0 // Access violation !!!
 end;

end;

Причем если ptest объявить в процедуре, то все работает...
Пробую дальше:
 asm
         mov     eax, [ebp-4]
         mov     eax, [eax+ptest]
         mov     ecx, self.ptest
         movapd  [eax], xmm0 // yes is right ;)
         movapd  [ecx], xmm0 // Access violation...          
 end;

значения еах и есх - разные, ptest объявлена в классе...


 
alpet ©   (2005-08-24 17:32) [21]

Есть такой указатель self, что на данные твоего обьекта указывает. При вызове метода класса он передается, как ни странно в eax. Обращение [self.ptest] (или self.ptest) компилятор преобразует соответственно в [eax + ptest]. Поэтому ты должен беречь содержимое этого регистра, а не травмировать.


{ ptest = $B100000  }
mov     eax, [eax+ptest] // eax = self
   mov     eax, [eax + 4]  // eax = ptest
mov     ecx, self.ptest    // eax is not self !!!
   mov     ecx, [eax + 4]  // ecx =  ???? PDWORD (ecx)^ may be 0
   mov     edx, [ecx]  // cause av


 
DMitryFox   (2005-08-24 17:53) [22]


> Есть такой указатель self, что на данные твоего обьекта
> указывает. При вызове метода класса он передается, как ни
> странно в eax. Обращение [self.ptest] (или self.ptest) компилятор
> преобразует соответственно в [eax + ptest]. Поэтому ты должен
> беречь содержимое этого регистра, а не травмировать.

Можно смело травмировать eax:
         
         mov     ebx, self
            mov     ebx, [ebp-4]
         mov     ecx, TForm1([ebx]).ptest
            mov     ecx, [ebx+$00002fc]

Судя по коду указатель на self можно достать со стека


 
alpet ©   (2005-08-24 18:13) [23]

DMitryFox   (24.08.05 17:53) [22]

Переменная  self в стеке присутствует в случае использования:

procedure TForm1.Func1;
begin
asm
 mov ebx, self   // mov ebx, [ebp - 4]
 ...  
end;
end;

и в eax, если тело функции состоит целиком из inline-assembler.

procedure TForm1.Func1;
asm
mov ebx, self
end;


потому что
begin компилируется в код пролога функции:
push   ebp              ;; save ebp
mov    ebp, esp         ;; set to stack ptr
push   ecx              ;; allocate 4 bytes in stack
mov    [ebp - 4], eax   ;; save eax to local var "self"

Но уже плюс что разобрался ;)


 
DMitryFox   (2005-08-24 18:17) [24]


> нафига тебе VirtualAlloc, если ты тоже самое можешь реализовать
> НЕ выходя за рамки ОР ?
>
> если ты НЕ в состоянии расчитать требуемые в дан.случае
> для GetMem()параметры, то нехрена тебе делать в WinAPI.

Так что-ли ?
 
   ptest := GetMemory($100);
   integer(ptest) := ((integer(ptest) + 15) div 16) * 16;

или наверное понятнее будет:
   ptest := GetMemory($100);
   ptest := pointer(((integer(ptest) + 15) div 16) * 16);

не, мне больше нравится так:

   ptest := GetMemory($100);
   while (integer(ptest) mod 16) <> 0 do
     inc(integer(ptest));

;)


 
alpet ©   (2005-08-24 18:39) [25]

DMitryFox   (24.08.05 18:17) [24]

А где HeapAlloc? :)


 
DMitryFox   (2005-08-24 18:53) [26]


> alpet ©   (24.08.05 18:39) [25]
>
> А где HeapAlloc? :)

А что это ? сорри, чайник я...
пойду срочно Фаронова почитаю :)


 
DMitryFox   (2005-08-24 19:28) [27]

Всем спасбо, вроде во всем, что интерисовало разобрался



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.10.30;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.039 c
4-1125052847
nslviv
2005-08-26 14:40
2005.10.30
Как запретить доступ к папке с помощью WinAPI?


1-1128423858
Cervus
2005-10-04 15:04
2005.10.30
Работа сервиса под несколькими пользовательскими аккаунтами


1-1128668625
Maverick
2005-10-07 11:03
2005.10.30
Сохранение пользовательских настроек


14-1129093537
Ega23
2005-10-12 09:05
2005.10.30
С днем рождения! 12 октября


4-1125186966
graveyard
2005-08-28 03:56
2005.10.30
как снять атрибут с файла





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский