2014-01-20 6 views
4

Я работаю над компилятором JIT и пытаюсь выяснить, как выводить правильные блоки очистки для управляемых типов, таких как строки.Как я могу получить адрес внутренних функций System.pas?

Разборка очищающей блока для функции, которая имеет одну локальную переменную типа string выглядит следующим образом:

0044333C 648910   mov fs:[eax],edx 
0044333F 6854334400  push $00443354 
00443344 8D45FC   lea eax,[ebp-$04] 
00443347 E81834FCFF  call @UStrClr 
0044334C C3    ret 
0044334D E9062BFCFF  jmp @HandleFinally 
00443352 EBF0    jmp $00443344 

К сожалению, у меня нет какой-либо хороший способ получить адреса @UStrClr и @HandleFinally поэтому мой JITter может их вставить. Они объявлены в System.Pas как _UStrClr и _HandleFinally, в разделе раздела, но, видимо, происходит некоторая «магия», потому что попытка использовать эти идентификаторы приводит к ошибке компилятора.

Итак, я попробовал процедуру ASM, где я объявил глобальный указатель и сказал mov func_ustr_clear, @UStrClear. На этот раз я не получу необъявленную ошибку идентификатора; Я получаю что-то еще более странное:

[DCC Error]: E2107 Operand size mismatch 

Так кто-нибудь есть идеи, как это сделать правильно?

+1

Возможно, вызов Finalize - это вариант? – Remko

+0

Если у вас есть madExcept, его исходный код является сокровищницей для таких методов. –

ответ

7

Попробуйте эти функции, чтобы получить адрес из UStrClr и HandleFinally:

function GetUStrClrAddress: Pointer; 
asm 
{$IFDEF CPUX64} 
    mov rcx, offset [email protected]; 
    mov @Result, rcx; 
{$ELSE} 
    mov @Result, offset [email protected]; 
{$ENDIF} 
end; 

function GetHandleFinallyAddress: Pointer; 
asm 
{$IFDEF CPUX64} 
    mov rcx, offset [email protected]; 
    mov @Result, rcx; 
{$ELSE} 
    mov @Result, offset [email protected]; 
{$ENDIF} 
end; 

Edit:

@ArnaudBouchez также предлагает некоторые дополнительные оптимизации. Прямо помещая значение в регистр возврата функции, функция выполняется немного быстрее.

function GetUStrClrAddress: Pointer; 
asm 
    {$ifdef CPU64} 
    mov rax,offset [email protected] 
    {$else} 
    mov eax,offset [email protected] 
    {$endif} 
end; 

Дальнейшее чтение с использованием ассемблера в Delphi можно найти здесь (и использование OFFSET ключевого слова), Assembly Expressions, Expression Classes.

+0

'@ Result' может быть заменен на' Result' здесь AFAIK. Или непосредственно реестр результатов, но Delphi asm сделает это за вас, так что «Результат» здесь просто отлично. +1 –

+1

Альтернативный более короткий/чистый код: 'function GetUStrClrAddress: Pointer; . ASM {$ IFDEF CPU64} мов Ракс, смещение системы @ UStrClr {$} еще MOV EAX, смещение системы @ UStrClr {$ ENDIF} конец;. ' –

+0

Aha! Ключевое слово 'Offset' было тем, что мне не хватало. Благодаря! –