Funzione di assemblaggio Delphi che ritorna una stringa lunga
Domanda
Sto cercando di imparare la programmazione di assemblaggio in linea a Delphi, ea tal fine ho trovato Questo Articolo Altamente utile.
Ora Desidero scrivere una funzione di assemblaggio Restituzione di una stringa lunga, in particolare un AnsiString
(per semplicità). Ho scritto
function myfunc: AnsiString;
asm
// eax = @result
mov edx, 3
mov ecx, 1252
call System.@LStrSetLength
mov [eax + 0], ord('A')
mov [eax + 1], ord('B')
mov [eax + 2], ord('C')
end;
.
Spiegazione:
Una funzione Restituzione di una stringa ha un parametro var result: AnsiString
invisibile (in questo caso), quindi, all'inizio della funzione, eax
dovrebbe tenere l'indirizzo della stringa risultante. Ho quindi impostato edx
e ecx
a 3 e 1252, rispettivamente, quindi chiamare System._LStrSetLength
. In effetti, lo faccio
_LStrSetLength(@result, 3, 1252)
.
Dove 3 è la nuova lunghezza della stringa (in caratteri= bytes) e 1252 è lo standard windows-1252 codepage.
Allora, sapendo che eax
è L'indirizzo del primo carattere della stringa , ho semplicemente impostato la stringa in "ABC". Ma non funziona - mi dà dati senza senso o eaccessviolation. Qual è il problema?
Aggiorna
Ora abbiamo due implementazioni apparentemente funzionanti di myfunc
, uno che impiega NewAnsiString
e uno che impiega LStrSetLength
. Non posso fare a meno di chiedermi se entrambi sono corretti, nel senso che non mettono incasinare la movimentazione interna delphi di stringhe (conteggio di riferimento, liberazione automatica, ecc.).
Soluzione
Devi usare un po 'di:
function myfunc: AnsiString;
asm
push eax // save @result
call system.@LStrClr
mov eax,3 {Length}
{$ifdef UNICODE}
mov edx,1252 // code page for Delphi 2009/2010
{$endif}
call system.@NewAnsiString
pop edx
mov [edx],eax
mov [eax],$303132
end;
.
restituirà una stringa "210" ...
Ed è sempre una buona idea di mettere un blocco {$ IFDEF Unicode} per avere il tuo codice compatibile con la versione di Delphi prima del 2009.
Altri suggerimenti
Con l'eccellente aiuto di A.bouchez, sono riuscito a correggere il mio codice, impiegando LStrSetLength
:
function myfunc: AnsiString;
asm
push eax
// eax = @result
mov edx, 3
mov ecx, 1252
call System.@LStrSetLength
pop eax
mov ecx, [eax]
mov [ecx], 'A'
mov [ecx] + 1, 'B'
mov [ecx] + 2, 'C'
end;
.