How to Understand the const source and var dest in the move Parameter
Summary by skyjacker
Contributor: Xiaofeng, liuxiao
Http://www.cnpack.org
Cnpack iv qq group: 130970
2007-01-31
(Please indicate the author, source, and integrity of the post)
Q:
Procedure move (const source; var DEST; count: integer );
The source and DEST parameters here do not indicate the data type. How should I use them?
VaR
XX, YY: array [0 .. 6] of char;
Begin
Fillchar (XX, 7, #0 );
XX: = 'abcdef ';
Move (XX, YY, 4 );
Move (XX [0], YY [0], 4)
// What are the differences between the above two statements?
End;
A:
XX, YY is a piece of data.
XX [0] is the first character of the data.
The starting addresses are the same, so the results of moving are the same.
Test code:
Procedure tform1.btnxclick (Sender: tobject );
VaR
XX, YY: array [0 .. 6] of char; // The content is stored in the stack.
A: array of char; // The content is in the heap. This can be understood why dynamic array a represents a string pointer.
Begin
Setlength (A, 10 );
Fillchar (XX, 7, #0 );
XX: = 'abcdef ';
A [0]: = 'a ';
A [1]: = 'B ';
Move (XX, YY, 4 );
Move (XX [0], YY [0], 4 );
Move (XX, a [0], 4 );
End;
By the way, explain the Pascal source code of move (Windows XP SP2 DELPHI6 + update2 ):
Procedure move (const source; var DEST; count: integer );
{$ Ifdef purepascal}
VaR
S, D: pchar;
I: integer;
Begin
S: = pchar (@ source );
D: = pchar (@ DEST );
If S = d then exit;
If Cardinal (d)> Cardinal (s) Then // essence 1: Be careful, don't overwrite Source
For I: = count-1 downto 0 do
D [I]: = s [I]
Else
For I: = 0 to count-1 do
D [I]: = s [I];
End;
{$ Else}
ASM
{-> Eax pointer to source}
{EdX pointer to destination}
{ECx count}
Push ESI
Push EDI
MoV ESI, eax
MoV EDI, EDX
MoV eax, ECx
Cmp edi, ESI
Ja @ down
Je @ exit
SAR ECx, 2 {copy count Div 4 Dwords}
JS @ exit
Rep movsd
MoV ECx, eax // excellent 2: Universal.
And ECx, 03 h
Rep movsb {copy count mod 4 bytes}
JMP @ exit
@ Down:
Lea ESI, [ESI + ECX-4] {point ESI to last DWORD of source}
Lea EDI, [EDI + ECX-4] {point EDI to last DWORD of DeST}
SAR ECx, 2 {copy count Div 4 Dwords}
JS @ exit
STD
Rep movsd
MoV ECx, eax
And ECx, 03 h {copy count mod 4 bytes}
Add ESI, 4-1 {point to last byte of rest}
Add EDI, 4-1
Rep movsb
ClD
@ Exit:
Pop EDI
Pop ESI
End;
{$ Endif}
Note:
Pointers in C/Pascal and other advanced languages are actually memory units that store addresses. The content (an address) stored by pointers refers to the content.
While I: integer is only a memory unit, and the content of I is an integer variable. @ I can get the address of I.
The non-type variable in Pascal is equivalent to void in C. The const source; var DEST; parameter can be understood as two memory areas. The implementation of these two parameters in assembly is to pass in the "address value" of source and DEST as the parameter, rather than the two variables themselves.
However, in the Pascal Implementation of the function, the source is the result obtained by referring to the input address again, so it still indicates the source before it is passed in. To obtain the address passed in the Assembly, use @ source. That is to say, this var encapsulates and hides the address fetch operation passed in when the function is called and the operation specified once in the function body.