Thread View: borland.public.cppbuilder.language.basm
15 messages
15 total messages
Started by Malcolm Smith
Fri, 20 Jul 2007 05:27
ASM conversion from Delphi to C++Builder
Author: Malcolm Smith
Date: Fri, 20 Jul 2007 05:27
Date: Fri, 20 Jul 2007 05:27
35 lines
2160 bytes
2160 bytes
I'm trying to convert this PAS code into a C++ unit but I am not having any
luck with the ASM code - it won't compile as is (although the PAS file
does).
Can someone please help with the ASM translation. I know I could just use
the .PAS file but I want to learn something along the way.
TRegisters = record
EAX,
EBX,
ECX,
EDX: Cardinal;
end;
procedure GetCPUID(Param: Cardinal; var Registers: TRegisters);
asm
PUSH EBX {save affected registers}
PUSH EDI
MOV EDI, Registers
XOR EBX, EBX {clear EBX register}
XOR ECX, ECX {clear ECX register}
XOR EDX, EDX {clear EDX register}
DB $0F, $A2 {CPUID opcode}
MOV TRegisters(EDI).&EAX, EAX {save EAX register}
MOV TRegisters(EDI).&EBX, EBX {save EBX register}
MOV TRegisters(EDI).&ECX, ECX {save ECX register}
MOV TRegisters(EDI).&EDX, EDX {save EDX register}
POP EDI {restore registers}
POP EBX
end;
--
Malcolm Smith
Re: ASM conversion from Delphi to C++Builder
Author: Bob Gonder
Date: Fri, 20 Jul 2007 14:44
Date: Fri, 20 Jul 2007 14:44
5 lines
1177 bytes
1177 bytes
Malcolm Smith wrote: >I'm trying to convert this PAS code into a C++ unit but I am not having any Ok, what does your C++ version look like?
Re: ASM conversion from Delphi to C++Builder
Author: Jonathan Benedicto
Date: Fri, 20 Jul 2007 16:02
Date: Fri, 20 Jul 2007 16:02
41 lines
2325 bytes
2325 bytes
Malcolm Smith wrote:
> I'm trying to convert this PAS code into a C++ unit but I am not having
> any luck with the ASM code - it won't compile as is (although the PAS file
> does).
>
> Can someone please help with the ASM translation. I know I could just use
> the .PAS file but I want to learn something along the way.
I'm no expert at ASM, but I'd guess that this would be the C++ translation:
struct TRegisters
{
DWORD EAX;
DWORD EBX;
DWORD ECX;
DWORD EDX;
};
void __fastcall GetCPUID( DWORD Param, TRegisters &Registers )
{
asm
{
PUSH EBX /* save affected registers */
PUSH EDI
MOV EDI, Registers
XOR EBX, EBX /* clear EBX register */
XOR ECX, ECX /* clear ECX register */
XOR EDX, EDX /* clear EDX register */
DB 0x0F, 0xA2 /* CPUID opcode */
MOV [EDI], EAX /* save EAX register */
MOV [EDI+4], EBX /* save EBX register */
MOV [EDI+8], ECX /* save ECX register */
MOV [EDI+12], EDX /* save EDX register */
POP EDI /* restore registers */
POP EBX
}
}
Worked for me at any rate.
Jon
Re: ASM conversion from Delphi to C++Builder
Author: Malcolm Smith
Date: Sat, 21 Jul 2007 11:33
Date: Sat, 21 Jul 2007 11:33
105 lines
3626 bytes
3626 bytes
Your translations is what I had, but it always failed to compile, like this:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRegisters Registers;
asm
{
PUSH EBX
PUSH EDI
MOV EDI, Registers
XOR EBX, EBX
XOR ECX, ECX
XOR EDX, EDX
DB 0x0F, 0xA2
MOV [EDI], EAX
MOV [EDI+4], EBX
MOV [EDI+8], ECX
MOV [EDI+12], EDX
POP EDI
POP EBX
}
}
When I moved the code to another function (like you did), it compiled.
What's the difference between the above and this:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRegisters Registers;
GetCPUID( 0, Registers );
}
void __fastcall TForm1::GetCPUID(DWORD Param, TRegisters &Registers)
{
asm
{
PUSH EBX
PUSH EDI
MOV EDI, Registers
XOR EBX, EBX
XOR ECX, ECX
XOR EDX, EDX
DB 0x0F, 0xA2
MOV [EDI], EAX
MOV [EDI+4], EBX
MOV [EDI+8], ECX
MOV [EDI+12], EDX
POP EDI
POP EBX
}
}
and why do I need to pass the DWORD Param (it would not compile without it).
--
Malcolm Smith
"Jonathan Benedicto" <invalid@nobody.com> wrote in message
news:46a0dcbb$1@newsgroups.borland.com...
> Malcolm Smith wrote:
>> I'm trying to convert this PAS code into a C++ unit but I am not having
>> any luck with the ASM code - it won't compile as is (although the PAS
>> file does).
>>
>> Can someone please help with the ASM translation. I know I could just
>> use the .PAS file but I want to learn something along the way.
>
> I'm no expert at ASM, but I'd guess that this would be the C++
> translation:
>
> struct TRegisters
> {
> DWORD EAX;
> DWORD EBX;
> DWORD ECX;
> DWORD EDX;
> };
>
> void __fastcall GetCPUID( DWORD Param, TRegisters &Registers )
> {
> asm
> {
> PUSH EBX /* save affected registers */
> PUSH EDI
> MOV EDI, Registers
> XOR EBX, EBX /* clear EBX register */
> XOR ECX, ECX /* clear ECX register */
> XOR EDX, EDX /* clear EDX register */
> DB 0x0F, 0xA2 /* CPUID opcode */
> MOV [EDI], EAX /* save EAX register */
> MOV [EDI+4], EBX /* save EBX register */
> MOV [EDI+8], ECX /* save ECX register */
> MOV [EDI+12], EDX /* save EDX register */
> POP EDI /* restore registers */
> POP EBX
> }
> }
>
> Worked for me at any rate.
>
> Jon
Re: ASM conversion from Delphi to C++Builder
Author: Bob Gonder
Date: Sat, 21 Jul 2007 16:58
Date: Sat, 21 Jul 2007 16:58
29 lines
1859 bytes
1859 bytes
Malcolm Smith wrote:
>Your translations is what I had, but it always failed to compile, like this:
>
>void __fastcall TForm1::Button1Click(TObject *Sender)
>{
>TRegisters Registers;
> MOV EDI, Registers
EDI now contains garbage because you loaded it from Registers.
You wanted to +point+ it to Registers.
Either mov edi, offset Registers
or lea edi, Registers
Whereas in the GetCPUID code, Registers is an alias for ECX
so
> MOV EDI, Registers
is really
> MOV EDI, ECX
which is fine.
>and why do I need to pass the DWORD Param (it would not compile without it).
Likely because that is the signature you have for it elsewhere?
Or because it is a class member (remember +this+)
You might also like to look at the code here
http://www.buraks.com/p3uns/
Re: ASM conversion from Delphi to C++Builder
Author: Malcolm Smith
Date: Sun, 22 Jul 2007 00:36
Date: Sun, 22 Jul 2007 00:36
43 lines
2209 bytes
2209 bytes
Must be something to do with *this* because my signature was correct. I'll
look at the link you also provided. Thanks.
--
Malcolm Smith
"Bob Gonder" <notbg@notmindspring.invalid> wrote in message
news:ma44a351l70894pknjbs3bgrgqpk0kacvl@4ax.com...
> Malcolm Smith wrote:
>
>>Your translations is what I had, but it always failed to compile, like
>>this:
>>
>>void __fastcall TForm1::Button1Click(TObject *Sender)
>>{
>>TRegisters Registers;
>
>> MOV EDI, Registers
>
> EDI now contains garbage because you loaded it from Registers.
> You wanted to +point+ it to Registers.
> Either mov edi, offset Registers
> or lea edi, Registers
>
> Whereas in the GetCPUID code, Registers is an alias for ECX
> so
>> MOV EDI, Registers
> is really
>> MOV EDI, ECX
> which is fine.
>
>>and why do I need to pass the DWORD Param (it would not compile without
>>it).
>
> Likely because that is the signature you have for it elsewhere?
> Or because it is a class member (remember +this+)
>
> You might also like to look at the code here
> http://www.buraks.com/p3uns/
>
>
>
Re: ASM conversion from Delphi to C++Builder
Author: Malcolm Smith
Date: Sun, 22 Jul 2007 00:50
Date: Sun, 22 Jul 2007 00:50
45 lines
2327 bytes
2327 bytes
Are there any good sites you can recommend for beginners (for C++).
Everything I've come across is Delphi related and mostly samples rather than
explanations. I did find one series of BASM for beginners, but again it is
Delphi related.
--
Malcolm Smith
"Bob Gonder" <notbg@notmindspring.invalid> wrote in message
news:ma44a351l70894pknjbs3bgrgqpk0kacvl@4ax.com...
> Malcolm Smith wrote:
>
>>Your translations is what I had, but it always failed to compile, like
>>this:
>>
>>void __fastcall TForm1::Button1Click(TObject *Sender)
>>{
>>TRegisters Registers;
>
>> MOV EDI, Registers
>
> EDI now contains garbage because you loaded it from Registers.
> You wanted to +point+ it to Registers.
> Either mov edi, offset Registers
> or lea edi, Registers
>
> Whereas in the GetCPUID code, Registers is an alias for ECX
> so
>> MOV EDI, Registers
> is really
>> MOV EDI, ECX
> which is fine.
>
>>and why do I need to pass the DWORD Param (it would not compile without
>>it).
>
> Likely because that is the signature you have for it elsewhere?
> Or because it is a class member (remember +this+)
>
> You might also like to look at the code here
> http://www.buraks.com/p3uns/
>
>
>
Re: ASM conversion from Delphi to C++Builder
Author: Ed Mulroy [TeamB]
Date: Sun, 22 Jul 2007 12:57
Date: Sun, 22 Jul 2007 12:57
83 lines
3335 bytes
3335 bytes
Either of these should be close. I say 'close' because I have not tested
them. As is the case with many if not most PCs my computer has the CPUID
command blocked for security purposes.
. Ed
-------------------------------------
#pragma pack(push, 1) /* struct packed on byte boundaries */
struct TRegisters
{
unsigned int EAX;
unsigned int EBX;
unsigned int ECX;
unsigned int EDX;
};
#pragma pack(pop)
void __fastcall GetCPUID_1(unsigned int cmd, TRegisters & regs)
{
_EBX = _ECX = _EDX = 0;
_EDI = reinterpret_cast<unsigned long>(& regs);
_EAX = cmd;
__emit__(0x0F, 0xA2); // insert opcode for GetCpuId
regs.EDX = _EDX;
regs.ECX = _ECX;
regs.EBX = _EBX;
regs.EAX = _EAX;
}
void __fastcall GetCPUID_2(unsigned int cmd, TRegisters & regs)
{
__asm {
xor edx,edx
mov ebx,edx
mov ecx,edx
mov eax,[cmd]
mov edi,esi /* _EDI = (unsigned long) & regs; */
db 0FH, 0A2H /* opcode for GetCpuId */
}
regs.EDX = _EDX;
regs.ECX = _ECX;
regs.EBX = _EBX;
regs.EAX = _EAX;
}
-------------------------------------
. Ed
> Malcolm Smith wrote in message
> news:46a047d3$1@newsgroups.borland.com...
>
> I'm trying to convert this PAS code into a C++ unit but I am not having
> any luck with the ASM code - it won't compile as is (although the PAS file
> does).
>
> Can someone please help with the ASM translation. I know I could just use
> the .PAS file but I want to learn something along the way.
>
>
> TRegisters = record
> EAX,
> EBX,
> ECX,
> EDX: Cardinal;
> end;
>
> procedure GetCPUID(Param: Cardinal; var Registers: TRegisters);
> asm
> PUSH EBX {save affected registers}
> PUSH EDI
> MOV EDI, Registers
> XOR EBX, EBX {clear EBX register}
> XOR ECX, ECX {clear ECX register}
> XOR EDX, EDX {clear EDX register}
> DB $0F, $A2 {CPUID opcode}
> MOV TRegisters(EDI).&EAX, EAX {save EAX register}
> MOV TRegisters(EDI).&EBX, EBX {save EBX register}
> MOV TRegisters(EDI).&ECX, ECX {save ECX register}
> MOV TRegisters(EDI).&EDX, EDX {save EDX register}
> POP EDI {restore registers}
> POP EBX
> end;
Re: ASM conversion from Delphi to C++Builder
Author: Bob Gonder
Date: Sun, 22 Jul 2007 12:58
Date: Sun, 22 Jul 2007 12:58
14 lines
1808 bytes
1808 bytes
Malcolm Smith wrote: >Are there any good sites you can recommend for beginners (for C++). >Everything I've come across is Delphi related and mostly samples rather than >explanations. I did find one series of BASM for beginners, but again it is >Delphi related. I learned from reading the manuals, and lots of programming. Trial-and-error, especially coupled with single stepping through the code in CPU view of the debugger, and watching the registers and flags change, is a great teacher. I also think Ed Mulroy has links on his site. http://edmulroy.org/prog7.htm#assy
Re: ASM conversion from Delphi to C++Builder
Author: Bob Gonder
Date: Sun, 22 Jul 2007 13:22
Date: Sun, 22 Jul 2007 13:22
55 lines
2313 bytes
2313 bytes
Ed Mulroy [TeamB] wrote:
>Either of these should be close. I say 'close' because I have not tested
Definately untested <G>
I would also be tempted to turn off stack frames for this function.
>void __fastcall GetCPUID_1(unsigned int cmd, TRegisters & regs)
> {
> _EBX = _ECX = _EDX = 0;
Premature clearing of passed variables.
_fastcall Order( EAX, EDX, ECX, SP[4], SP[8].... )
> _EDI = reinterpret_cast<unsigned long>(& regs);
_EDI = _EDX
EDI and EBX not preserved as required
(unless compiler is doing hidden magic)
> _EAX = cmd;
NOP, cmd is passed in eax
> __emit__(0x0F, 0xA2); // insert opcode for GetCpuId
> regs.EDX = _EDX;
> regs.ECX = _ECX;
> regs.EBX = _EBX;
> regs.EAX = _EAX;
> }
>
>void __fastcall GetCPUID_2(unsigned int cmd, TRegisters & regs)
> {
> __asm {
> xor edx,edx
> mov ebx,edx
> mov ecx,edx
> mov eax,[cmd]
> mov edi,esi /* _EDI = (unsigned long) & regs; */
Same issues, plus new one:
Where did esi come from?
> db 0FH, 0A2H /* opcode for GetCpuId */
> }
>
> regs.EDX = _EDX;
Does the compiler "know" that you trounced edx (regs)?
> regs.ECX = _ECX;
> regs.EBX = _EBX;
> regs.EAX = _EAX;
> }
Re: ASM conversion from Delphi to C++Builder
Author: Malcolm Smith
Date: Sun, 22 Jul 2007 23:20
Date: Sun, 22 Jul 2007 23:20
34 lines
2296 bytes
2296 bytes
> I also think Ed Mulroy has links on his site. > http://edmulroy.org/prog7.htm#assy Is that link correct...I can't seem to browse to it (including http://edmulroy.org) ....just did a quick google and came up with http://edmulroy.portbridge.com/prog7.htm#assy - I assume this is the same. -- Malcolm Smith "Bob Gonder" <notbg@notmindspring.invalid> wrote in message news:h5k6a3djoife9ucica956qrc8i1s1b5hlc@4ax.com... > Malcolm Smith wrote: > >>Are there any good sites you can recommend for beginners (for C++). >>Everything I've come across is Delphi related and mostly samples rather >>than >>explanations. I did find one series of BASM for beginners, but again it >>is >>Delphi related. > > I learned from reading the manuals, and lots of programming. > Trial-and-error, especially coupled with single stepping through > the code in CPU view of the debugger, and watching the registers > and flags change, is a great teacher. > > I also think Ed Mulroy has links on his site. > http://edmulroy.org/prog7.htm#assy > >
Re: ASM conversion from Delphi to C++Builder
Author: Ed Mulroy [TeamB]
Date: Mon, 23 Jul 2007 13:09
Date: Mon, 23 Jul 2007 13:09
10 lines
1504 bytes
1504 bytes
> I also think Ed Mulroy has links on his site. > http://edmulroy.org/prog7.htm#assy Opps, typo. Try this instead: > http://www.mulroy.org/prog7.htm#assy . Ed > Bob Gonder wrote in message > news:h5k6a3djoife9ucica956qrc8i1s1b5hlc@4ax.com...
Re: ASM conversion from Delphi to C++Builder
Author: Ed Mulroy [TeamB]
Date: Mon, 23 Jul 2007 13:21
Date: Mon, 23 Jul 2007 13:21
124 lines
4139 bytes
4139 bytes
> I would also be tempted to turn off stack frames for this function.
In that case you would be jumping out of a plane without your parachute.
Better to use
__declspec(naked)
and write every byte of the assembly code yourself.
>>void __fastcall GetCPUID_1(unsigned int cmd, TRegisters & regs)
>> {
>> _EBX = _ECX = _EDX = 0;
>
> Premature clearing of passed variables.
> _fastcall Order( EAX, EDX, ECX, SP[4], SP[8].... )
> ...
> EDI and EBX not preserved as required
Not so.
Compile the source from the command line with the -S option to see the
generated code in a *.asm file.
SOP for since at least TC 2 is to push registers that are explicitly used.
Between the possiblity of fancy code masking its detection and paranoia, it
is an implicit requirement for a programmer to check the generated code for
any source using inline assembly or pseudo-registers to insure that what is
required has been saved and restored.
---------------------
; void __fastcall GetCPUID_1(unsigned int cmd, TRegisters & regs)
;
push ebp
mov ebp,esp
push ecx
push ebx
push esi
push edi
mov esi,edx
mov dword ptr [ebp-4],eax
;
; {
; _EBX = _ECX = _EDX = 0;
;
---------------------
>> mov edi,esi /* _EDI = (unsigned long) & regs; */
>
> Same issues, plus new one:
> Where did esi come from?
GetCPUID_1's generated code shows esi contains ®s
---------------------
; _EDI = reinterpret_cast<unsigned long>(& regs);
;
;
mov edi,esi
---------------------
> Does the compiler "know" that you trounced edx (regs)?
It does not use the value so does not need to know.
. Ed
> Bob Gonder wrote in message
> news:37l6a3dnmrn3m9blstu4dqvmmjah97nbif@4ax.com...
>
>>Either of these should be close. I say 'close' because I have not tested
>
> Definately untested <G>
>
> I would also be tempted to turn off stack frames for this function.
>
>>void __fastcall GetCPUID_1(unsigned int cmd, TRegisters & regs)
>> {
>> _EBX = _ECX = _EDX = 0;
>
> Premature clearing of passed variables.
> _fastcall Order( EAX, EDX, ECX, SP[4], SP[8].... )
>
>> _EDI = reinterpret_cast<unsigned long>(& regs);
>
> _EDI = _EDX
> EDI and EBX not preserved as required
> (unless compiler is doing hidden magic)
>
>> _EAX = cmd;
>
> NOP, cmd is passed in eax
>
>> __emit__(0x0F, 0xA2); // insert opcode for GetCpuId
>> regs.EDX = _EDX;
>> regs.ECX = _ECX;
>> regs.EBX = _EBX;
>> regs.EAX = _EAX;
>> }
>>
>>void __fastcall GetCPUID_2(unsigned int cmd, TRegisters & regs)
>> {
>> __asm {
>> xor edx,edx
>> mov ebx,edx
>> mov ecx,edx
>> mov eax,[cmd]
>> mov edi,esi /* _EDI = (unsigned long) & regs; */
>
> Same issues, plus new one:
> Where did esi come from?
>
>> db 0FH, 0A2H /* opcode for GetCpuId */
>> }
>>
>> regs.EDX = _EDX;
>
> Does the compiler "know" that you trounced edx (regs)?
>
>> regs.ECX = _ECX;
>> regs.EBX = _EBX;
>> regs.EAX = _EAX;
>> }
>
>
Re: ASM conversion from Delphi to C++Builder
Author: Bob Gonder
Date: Mon, 23 Jul 2007 16:41
Date: Mon, 23 Jul 2007 16:41
20 lines
1718 bytes
1718 bytes
Ed Mulroy [TeamB] wrote: >> I would also be tempted to turn off stack frames for this function. > >In that case you would be jumping out of a plane without your parachute. It's small enough, and no local variables, so no problems. Feathers don't need parachutes. >Better to use >__declspec(naked) >and write every byte of the assembly code yourself. Oooh, sexy...I like it. That's what I intended to mean. I was thinking a local pragma, but this does the job. __declspec(naked) void __fastcall GetCPUID(unsigned int cmd, TRegisters & regs)
Re: ASM conversion from Delphi to C++Builder
Author: Ed Mulroy [TeamB]
Date: Mon, 23 Jul 2007 17:19
Date: Mon, 23 Jul 2007 17:19
33 lines
2011 bytes
2011 bytes
>>Better to use >>__declspec(naked) >>and write every byte of the assembly code yourself. > > Oooh, sexy...I like it. Be careful when using it. It truely is naked. When the function ends there isn't even a RET or RETN statement - you must add that yourself. . Ed > Bob Gonder wrote in message > news:rkl9a39ctqn0ims2tejfb8scko90vemda0@4ax.com... > >>> I would also be tempted to turn off stack frames for this function. > >> In that case you would be jumping out of a plane without your >> parachute. > > It's small enough, and no local variables, so no problems. > Feathers don't need parachutes. > >>Better to use >>__declspec(naked) >>and write every byte of the assembly code yourself. > > Oooh, sexy...I like it. > > That's what I intended to mean. > I was thinking a local pragma, but this does the job. > > __declspec(naked) > void __fastcall GetCPUID(unsigned int cmd, TRegisters & regs)
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads