🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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
#14
Author: Malcolm Smith
Date: Fri, 20 Jul 2007 05:27
35 lines
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
#15
Author: Bob Gonder
Date: Fri, 20 Jul 2007 14:44
5 lines
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
#16
Author: Jonathan Benedicto
Date: Fri, 20 Jul 2007 16:02
41 lines
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
#17
Author: Malcolm Smith
Date: Sat, 21 Jul 2007 11:33
105 lines
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
#18
Author: Bob Gonder
Date: Sat, 21 Jul 2007 16:58
29 lines
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
#19
Author: Malcolm Smith
Date: Sun, 22 Jul 2007 00:36
43 lines
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
#20
Author: Malcolm Smith
Date: Sun, 22 Jul 2007 00:50
45 lines
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
#21
Author: Ed Mulroy [TeamB]
Date: Sun, 22 Jul 2007 12:57
83 lines
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
#22
Author: Bob Gonder
Date: Sun, 22 Jul 2007 12:58
14 lines
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
#23
Author: Bob Gonder
Date: Sun, 22 Jul 2007 13:22
55 lines
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
#28
Author: Malcolm Smith
Date: Sun, 22 Jul 2007 23:20
34 lines
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
#24
Author: Ed Mulroy [TeamB]
Date: Mon, 23 Jul 2007 13:09
10 lines
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
#25
Author: Ed Mulroy [TeamB]
Date: Mon, 23 Jul 2007 13:21
124 lines
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 &regs

---------------------
 ;   _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
#26
Author: Bob Gonder
Date: Mon, 23 Jul 2007 16:41
20 lines
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
#27
Author: Ed Mulroy [TeamB]
Date: Mon, 23 Jul 2007 17:19
33 lines
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