tobjectpascal
asked on
Assembly Problem
procedure TForm1.Button2Click(Sender : TObject);
Var
Str: String;
Str2: String;
P: Pointer;
begin
Str2:='ABCDEF';
Str:='abcdef';
Asm
push esi;
push edi;
mov edi,[Str]; //abcde
Mov esi,[Str2]; //ABCDE
mov al,[esi]; //al now = 65
Mov [esi],al; //make this char 65 (yes i know, but even this errors :| )
pop edi;
pop esi;
End;
showMessage(Str);
end;
why does that ERROR?! i'm going to give up at this rate.
Var
Str: String;
Str2: String;
P: Pointer;
begin
Str2:='ABCDEF';
Str:='abcdef';
Asm
push esi;
push edi;
mov edi,[Str]; //abcde
Mov esi,[Str2]; //ABCDE
mov al,[esi]; //al now = 65
Mov [esi],al; //make this char 65 (yes i know, but even this errors :| )
pop edi;
pop esi;
End;
showMessage(Str);
end;
why does that ERROR?! i'm going to give up at this rate.
ASKER
Var
Str: String;
Str2: String;
P: Pointer;
begin
Str2:='ABCDEF';
Str:='abcdef';
SetLength(Str,6); //This fixes the code!, why? i'm not sure.
Asm
push esi;
push edi;
mov edi,[Str]; //abcde
Mov esi,[Str2]; //ABCDE
mov al,[esi]; //al now = 65
Mov [edi],al; //make this char 65 (yes i know, but even this errors :| )
pop edi;
pop esi;
End;
showMessage(Str);
Str: String;
Str2: String;
P: Pointer;
begin
Str2:='ABCDEF';
Str:='abcdef';
SetLength(Str,6); //This fixes the code!, why? i'm not sure.
Asm
push esi;
push edi;
mov edi,[Str]; //abcde
Mov esi,[Str2]; //ABCDE
mov al,[esi]; //al now = 65
Mov [edi],al; //make this char 65 (yes i know, but even this errors :| )
pop edi;
pop esi;
End;
showMessage(Str);
ASKER
// FillChar(Str[1],6,ord('?') );
// SetLength(Str,6);
// Str:=Str+'?';
Any of these Get the code working, my logical assumption is that the Compiler disregards Str because it's not used in my code... but if that were true it does not explain why you can extract from the string's array but not put it back.
// SetLength(Str,6);
// Str:=Str+'?';
Any of these Get the code working, my logical assumption is that the Compiler disregards Str because it's not used in my code... but if that were true it does not explain why you can extract from the string's array but not put it back.
ASKER
asm
Lea eax,Str;
Mov edx,6;
Call System.@LStrSetLength;
End;
sorts it though.
Lea eax,Str;
Mov edx,6;
Call System.@LStrSetLength;
End;
sorts it though.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
lea eax, [Str] // Load str address
call UniqueString // Make unique
So i'm guessing that SetLength does the same as UniqueString ?
ASKER
anyway, thanks rlibby for all your help, As you probably can tell i'm trying to Learn BASM, problem i'm having is when to Push and when to move from Right to Left and when to Push to EAX EDX and ECX in that order...
But i think i'm slowly getting there :)
Thanks again.
But i think i'm slowly getting there :)
Thanks again.
Both the SetLength and UniqueString calls end up in the same place, which is _NewAnsiString, which handles the problem that the Delphi docs mention:
>> Only in cases where an application casts a string to a PChar and then modifies the contents of the string must UniqueString be used.
which is in effect what you are doing with the asm code.
Anyways, best of luck on your BASM work... its not always easy, but its usually quite rewarding.
Russell
>> Only in cases where an application casts a string to a PChar and then modifies the contents of the string must UniqueString be used.
which is in effect what you are doing with the asm code.
Anyways, best of luck on your BASM work... its not always easy, but its usually quite rewarding.
Russell
ASKER
Well i know i'm not offering any points, but this is really confusing me?
lea eax, [Str]
not the same as
mov eax,offset [str]
or
mov eax,str
I understand that's there's segments and indexes, Seg:howfarinto the segment
But Windows does not seem the same as when i touched on DOS assembly...
Load Effective Address
mov eax,Adre;
it's not a problem, as i can jsut use Lea but how on earth do you know what needs Lea... ugh
I can option up another question just for finding out the difference lol... but thanks for the help.
lea eax, [Str]
not the same as
mov eax,offset [str]
or
mov eax,str
I understand that's there's segments and indexes, Seg:howfarinto the segment
But Windows does not seem the same as when i touched on DOS assembly...
Load Effective Address
mov eax,Adre;
it's not a problem, as i can jsut use Lea but how on earth do you know what needs Lea... ugh
I can option up another question just for finding out the difference lol... but thanks for the help.
LEA (load effective address) loads a 32 bit address with the *address* of the operand, vs. a MOV, which will set the 32 bit address with the *value* of the operand. Think of it like this:
Pointer(@Str) // This is like LEA
Pointer(Str) // This is like MOV
The difference usually comes down to passing a param by value or by reference. Take for example the functions:
- LStrSetLength
- UniqueString
They are both defined as taking a "var String" parameter (by reference), thus the LEA would be use to setup the EAX register for the call to either of these. If you were calling a function that took a pchar / string constant, then the MOV would be used instead.
Russell
ASKER
ahhh thank you very much :)
You are one of the few true experts in this forum :)
You are one of the few true experts in this forum :)
ASKER
Rlibby...here's why i was confused (taken from my example above)
mov al,[esi]; //al now = 65
Gives 65 (the data from the pointer, not the pointer address)
mov al,esi; //al now = 65
Will not compile because it's passing the address to al, and the address is bigger than 8 bytes
mov eax,[esi]; //passes the Data, not the Value
mov eax,esi; //passes the Pointer to the data not the value
So if it passes the pointer...
why not
Mov Eax,Str;
instead of
lea eax, [Str]
Technically they should both be the same result, but I've checked, it's not....
Which is why i got confused why not just Mov Eax, it's not passing the data but the pointer....
This is going to kill me... Rlibby, if you answer this i'll throw you my last remainig few points in a new thread just accept it when i created it :P
mov al,[esi]; //al now = 65
Gives 65 (the data from the pointer, not the pointer address)
mov al,esi; //al now = 65
Will not compile because it's passing the address to al, and the address is bigger than 8 bytes
mov eax,[esi]; //passes the Data, not the Value
mov eax,esi; //passes the Pointer to the data not the value
So if it passes the pointer...
why not
Mov Eax,Str;
instead of
lea eax, [Str]
Technically they should both be the same result, but I've checked, it's not....
Which is why i got confused why not just Mov Eax, it's not passing the data but the pointer....
This is going to kill me... Rlibby, if you answer this i'll throw you my last remainig few points in a new thread just accept it when i created it :P
Yes, technically they are the same, therefore I can understand the confusion. The problem comes down to the inline compiler in Delphi. Take for instance the following asm code block within a procedure called Test:
procedure Test;
var X: Integer;
begin
asm
mov X, 100
mov eax, X
end;
ShowMessage(IntToStr(X));
end;
The variable X is pointer to the memory location at EBP-4 (this is KEY). If you perform the following:
mov eax, X
The inline assembler will turn your code into:
mov eax, [ebp-4]
Which is exactly what we DONT want. (we don't want the value, we want the address). In fact, the inline compiler generates the same code for both usages:
mov eax [X]
mov eax, X
Its really not the compiler's fault either, as only LEA can be used to transfer a calculated addresss such as
[ebp-4]
In order to do that with a MOV, you would have to do:
mov eax, ebp-4
Which won't fly, thus the reason for LEA.....
------
Hopefully I didn't confuse you more. ;-)
Russell
wh
the EAX register will end up with the value 100. Keep in mind that variable X is nothing more than a pointer to 4 bytes of memory. It
procedure Test;
var X: Integer;
begin
asm
mov X, 100
mov eax, X
end;
ShowMessage(IntToStr(X));
end;
The variable X is pointer to the memory location at EBP-4 (this is KEY). If you perform the following:
mov eax, X
The inline assembler will turn your code into:
mov eax, [ebp-4]
Which is exactly what we DONT want. (we don't want the value, we want the address). In fact, the inline compiler generates the same code for both usages:
mov eax [X]
mov eax, X
Its really not the compiler's fault either, as only LEA can be used to transfer a calculated addresss such as
[ebp-4]
In order to do that with a MOV, you would have to do:
mov eax, ebp-4
Which won't fly, thus the reason for LEA.....
------
Hopefully I didn't confuse you more. ;-)
Russell
wh
the EAX register will end up with the value 100. Keep in mind that variable X is nothing more than a pointer to 4 bytes of memory. It
>> wh
>>
>> the EAX register will end up with the value 100. Keep in mind that variable X is nothing more than a pointer to 4 bytes of memory. It
Please ignore my edits that I forget to cleanup before posting
Russell
>>
>> the EAX register will end up with the value 100. Keep in mind that variable X is nothing more than a pointer to 4 bytes of memory. It
Please ignore my edits that I forget to cleanup before posting
Russell
ASKER
ahhh interesting, thank you, i've got about 35 points remaming, you can have them :)
Dont' worry about it.
Russell
Russell
ASKER
Serously.... I'm on to something here..
var
s: String;
begin
s:='hello world';
asm
lea eax,s;
call uniquestring; //fine
mov eax,s;
call showmessage; //fine
end;
var
s: String;
begin
s:='hello world';
asm
// lea eax,s;
mov eax,s;
call uniquestring; //boooooooom
// mov eax,s;
lea eax,s;
call showmessage; //booooooooom
end;
That's got to be Borland at fault.... not accepting the same method of getting the address twice, that can't be right i know.
The only rule i can see is, if it crashes, try the other way lol
var
s: String;
begin
s:='hello world';
asm
lea eax,s;
call uniquestring; //fine
mov eax,s;
call showmessage; //fine
end;
var
s: String;
begin
s:='hello world';
asm
// lea eax,s;
mov eax,s;
call uniquestring; //boooooooom
// mov eax,s;
lea eax,s;
call showmessage; //booooooooom
end;
That's got to be Borland at fault.... not accepting the same method of getting the address twice, that can't be right i know.
The only rule i can see is, if it crashes, try the other way lol
Seriously, the rules are pretty straight forward.
1 - MOV cannot be used in Delphi's inline asm to transfer an address. LEA must be used to transfer an address.
2 - Functions that accept var Value will require a LEA to setup the register.
3 - Functions that accept (const) Value will require a MOV to setup the register.
The difference comes down to passing a param by value or by reference. UniqueString requires a var String (by reference). I already explained why MOV EAX, S isn't going to cut it for that. It generates a:
mov eax, [ebp-4]
which moves the VALUE not the address, so LEA *must* be used for var values. The ShowMessage routine on the other hand expects a string value, so MOV must be used to setup the eax register. If you use LEA, then its going to push the address and not the value, and the routine has no way of knowing the difference. And I'm sure you have probably read other articles on asm, which is why you are under the premise that:
MOV EAX, REG
and
LEA EAX, [REG]
are the same. But you have to understand that those docs are usually tailored to MASM / raw ASM development, and that it doesn't always apply to inline assemblers such as Delphi's. (Eg you can't use the EIP reg in the inline assembler, etc..). In this case MOV and LEA do NOT generate the same results.
Russell
1 - MOV cannot be used in Delphi's inline asm to transfer an address. LEA must be used to transfer an address.
2 - Functions that accept var Value will require a LEA to setup the register.
3 - Functions that accept (const) Value will require a MOV to setup the register.
The difference comes down to passing a param by value or by reference. UniqueString requires a var String (by reference). I already explained why MOV EAX, S isn't going to cut it for that. It generates a:
mov eax, [ebp-4]
which moves the VALUE not the address, so LEA *must* be used for var values. The ShowMessage routine on the other hand expects a string value, so MOV must be used to setup the eax register. If you use LEA, then its going to push the address and not the value, and the routine has no way of knowing the difference. And I'm sure you have probably read other articles on asm, which is why you are under the premise that:
MOV EAX, REG
and
LEA EAX, [REG]
are the same. But you have to understand that those docs are usually tailored to MASM / raw ASM development, and that it doesn't always apply to inline assemblers such as Delphi's. (Eg you can't use the EIP reg in the inline assembler, etc..). In this case MOV and LEA do NOT generate the same results.
Russell
ASKER
Ok At Last... lol sorry to be a pain in the rear end russel, but i think i finally understand it, I managed to code a routine that works... lol and yes thank you for your paitients, if the help file requires a return to a Pointer i use Lea, or i pass by Var, otherwise i use Mov and pass by value..
I think i'm starting to understand :D I do find it interesting that they Delphi has internal names for example LstrCat will cause an error and instead it requires LstrCat3 kinda odd but not a problem Mucho Gracias :)
procedure TForm1.Button1Click(Sender
var
Ret: Integer;
ResString,Val,s,sub: String;
Const
S2: String = 'Position: ';
begin
s:='hello world';
sub:='llo';
asm
lea eax,s;
call uniquestring;
push eax;
// call showmessage;
mov eax,sub;
pop edx;
Call system.@lstrpos;
mov ret,eax;
lea edx,val;
Call Inttostr;
Lea Eax,ResString;
Mov Ecx,Val;
Mov Edx,S2;
Call System.@LStrCat3;
Mov Eax,ResString;
call showmessage;
end;
ASKER
s: String;
begin
SetLength(s,6);
asm
mov Esi,S;
mov cx,65;
mov [esi],cx;
end;
showMessage(S);
Is the solution, for some reason it does not like 8 bit registers going in.... odd