2010-07-22 73 views
2

我想學習Delphi中的內聯彙編編程,爲此我發現this article非常有幫助。Delphi彙編函數返回一個長字符串

現在我想編寫一個返回一個長字符串的彙編函數,特別是AnsiString(爲簡單起見)。我已經寫

function myfunc: AnsiString; 
asm 
    // eax = @result 
    mov edx, 3 
    mov ecx, 1252 
    call [email protected] 
    mov [eax + 0], ord('A') 
    mov [eax + 1], ord('B') 
    mov [eax + 2], ord('C') 
end; 

說明:

返回一個字符串的函數有一個看不見的var result: AnsiString(在這種情況下)參數,所以,在函數的開始,eax應持有所產生的字符串的地址。然後我分別將edxecx設置爲3和1252,然後撥打System._LStrSetLength。實際上,我做

_LStrSetLength(@result, 3, 1252) 

其中3是字符串的新長度(字符數=字節),1252是標準windows-1252代碼頁。

然後,知道eaxthe address of the first character of the string,我只需將字符串設置爲「ABC」。但它不起作用 - 它給我無意義的數據或EAccessViolation。問題是什麼?

更新

現在我們的myfunc兩個看似工作的實施,一個採用NewAnsiString和一個採用LStrSetLength。我不禁想知道它們是否都是正確的,因爲它們並不妨礙Delphi對字符串的內部處理(引用計數,自動釋放等)。

+0

對於Delphi/Asm的問題,Embarcadero的BASM論壇也很有用。使用字符串,你可能也對這個線程感興趣:http://forums.embarcadero.com/thread.jspa?threadID=20231 – PhiS 2010-07-23 08:49:59

回答

3

你必須使用某種:

function myfunc: AnsiString; 
asm 
    push eax // save @result 
    call [email protected] 
    mov eax,3     {Length} 
{$ifdef UNICODE} 
    mov edx,1252 // code page for Delphi 2009/2010 
{$endif} 
    call [email protected] 
    pop edx 
    mov [edx],eax 
    mov [eax],$303132 
end; 

它會返回一個「210」串...

它總是把一個{$ IFDEF UNICODE}一個好主意,以阻止之前的2009年

+0

這個工作。如果我正確理解了代碼,'@ result'是固定的,並且是一個指向字符串的指針,它是一個指針本身,所以字符串的第一個字符在概念上是'(@result)^^',而不是'(@result)^'? – 2010-07-22 21:30:28

+0

確實。你在這裏有重點。 – 2010-07-23 07:19:02

+0

關於要調用的函數,只調用NewAnsiString會導致一些內存泄漏。 所以調用LStrSetLength是最好的選擇:如果結果字符串是'',它將調用NewAnsiString,如果結果字符串已經包含字符,它將調用ReallocMem。 最快的方法是使用LStrClr,然後是NewAnsiString,因爲ReallocMem會移動之前存儲在結果中的數據。請參閱System.pas中的StringOfChar()函數代碼我已更新我的示例。 – 2010-07-23 07:26:57

1

隨着A.Bouchez的優秀援助有你的代碼用Delphi版本兼容,我設法糾正自己的代碼,採用LStrSetLength

function myfunc: AnsiString; 
asm 

    push eax 

    // eax = @result 
    mov edx, 3 
    mov ecx, 1252 
    call [email protected] 

    pop eax 

    mov ecx, [eax] 

    mov [ecx], 'A' 
    mov [ecx] + 1, 'B' 
    mov [ecx] + 2, 'C' 

end;