Solved

Assembler CMP with Delphi 3

Posted on 1998-07-27
14
631 Views
Last Modified: 2010-04-03
I want to compare 2 memory blocks using the following function:

function ByteComp(ptr1,ptr2:pointer;length:integer):boolean;assembler;
asm
push     ds
push     edi
push     esi
mov      ax,ds
mov      ecx,length
les      esi,ptr1      <- error #1
lds      edi,ptr2      <- error #2  
mov      es,ax
repe     cmpsb
xor      ax,ax
test     ecx,ecx
jz       @ende
inc      ax
@ende:
pop   esi
pop   edi
pop   ds
end;

but I cant compile this thing (using Delphi 3.0/NT 4.0).

I tried (should work with the flat memory model)

 [...]
 mov edi,ptr1
 mov esi,ptr2
 [...]

and I get a access violation at the repe ...

btw - does the addr() function include the segment, or is it only the offset ?
0
Comment
Question by:egono
14 Comments
 
LVL 4

Expert Comment

by:d003303
ID: 1358739
Hum, don't know assembler very well. But I guess it is about the memory model. You don't have segment:offset pointers in the 32 bit environment any more, the pointers are all linear.

Slash/d003303
0
 
LVL 2

Author Comment

by:egono
ID: 1358740
hi slash

do you have another (fast) solution to compare 2 memory blocks ?

0
 
LVL 2

Author Comment

by:egono
ID: 1358741
very strange things happens:

function ByteComp(ptr1,ptr2:pointer;length:integer):boolean;assembler;
asm
push     edi
push     esi
cld
mov      ax,ds
mov      ecx,length    <-- ecx=50 - ok
mov      esi,ptr1      <-- Debugger says that esi=35 ??????
mov      edi,ptr2      <-- edi=2 - ok
mov      es,ax
repe     cmpsb
xor      eax,eax
test     ecx,ecx
jz       @ende
inc      eax
@ende:
pop      esi
pop      edi
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if ByteComp(pointer(1),pointer(2),50) then ShowMessage('TRUE');
end;

ohh I'm very confused ...
0
 
LVL 4

Accepted Solution

by:
erajoj earned 150 total points
ID: 1358742
Hi,
I love assembler, but why not use: function SysUtils.CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
I mean, it just sits there and waits for you! :-)

BTW, it looks like this:

function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
asm
        PUSH    ESI
        PUSH    EDI
        MOV     ESI,P1
        MOV     EDI,P2
        MOV     EDX,ECX
        XOR     EAX,EAX
        AND     EDX,3
        SHR     ECX,1
        SHR     ECX,1
        REPE    CMPSD
        JNE     @@2
        MOV     ECX,EDX
        REPE    CMPSB
        JNE     @@2
@@1:    INC     EAX
@@2:    POP     EDI
        POP     ESI
end;

/// John
0
 
LVL 3

Expert Comment

by:KE
ID: 1358743
Well, someone posted an answer while I was submitting... it should go for an answer !

Try this one:

function ByteComp(ptr1,ptr2:pointer;length:integer):Integer;assembler;
asm
  push     esi
  push     edi
  mov      esi,ptr1
  mov      edi,ptr2
  mov      ecx,length
  cld
  repe     cmpsb
  mov      eax,ecx
  pop   edi
  pop   esi
end;

Take care that your memoryblocks are of equal size or at least the length is set to the smallest block :-)

The routine returns the number of bytes left to be compared which in some cases could be usefull.


My test routine:

procedure TForm1.Button1Click(Sender: TObject);
Var
  s1,s2: String;
  x : Boolean;
begin
  s1 := 'Hello World';
  s2 := 'Hello Words';
  x := ByteComp( PChar(s1), PChar(s2), Length(s1) ) = 0;
end;


0
 
LVL 4

Expert Comment

by:erajoj
ID: 1358744
Hi again,
Take a good look at the RTL/VCL sourcecode. Lots and lots of really good stuff in there!

/// John
0
 
LVL 2

Author Comment

by:egono
ID: 1358745
ok erajoj,

CompareMem works and if you tell me why (and why my function dont) you get the 150 points.

function ByteComp(ptr1,ptr2:pointer;length:integer):boolean;assembler;
asm
push     edi
push     esi
cld
mov      ax,ds
mov      ecx,length
mov      esi,ptr1
mov      edi,ptr2
mov      es,ax
repe     cmpsb
xor      eax,eax
test     ecx,ecx
jz       @ende
inc      eax
@ende:
pop      esi
pop      edi
end;

meanwhile I get the answer on my own ...
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 2

Author Comment

by:egono
ID: 1358746
Hi KE

sorry erajoj's answer is very good, so I give him the points ...

0
 
LVL 2

Author Comment

by:egono
ID: 1358747
to KE again,

you can make your function a little bit faster :-) ...

0
 
LVL 2

Author Comment

by:egono
ID: 1358748
for all the other boys and girls who buy the answer:

My first try (with les/lds) wouldn't work because we are in a flat memory.

The second one should work, *BUT* delphi does a little bit optimizing on its own (not documented in my version of delphi). It dosnt puts the three parameters on the stack, as it should. The parameters are in the registers (eax=ptr1, edx=ptr2, ecx=length), so my "mov ax,ds" destroyes the first parameter and the function crashs.

thats it (it costs me about 5 hours :-( ) ...

The posted answer includes the optimal way to do the thing I want.

0
 
LVL 2

Author Comment

by:egono
ID: 1358749
erajoj - you have the points (take a look at my comments) ...
0
 
LVL 4

Expert Comment

by:erajoj
ID: 1358750
Hi Again "egono",
Well; your function works, almost, you just mess up EAX (hard bug to detect) and you have to change jz to jnz. See below:

asm
       push     edi
       push     esi
       cld
//       mov      ax,ds    // here's where you mess up EAX that's needed...
       mov      ecx,length
       mov      esi,ptr1 // ...here, see below
       mov      edi,ptr2
// why you do the following two lines, I don't know?!?
//       mov      ax,ds    // has to be done here, but is not needed
       mov      es,ax // not needed at all here
       repe     cmpsb
       xor      eax,eax
       test     ecx,ecx
       jnz      @ende // changed here
       inc      eax
       @ende:
       pop      esi
       pop      edi
end;

Here is your code with some optimising, after studying the disassembly view during debugging in Delphi for the last hour, or so:
(Tip: Set HKEY_CURRENT_USER\Software\Borland\Delphi\3.0\Debugging\EnableCPU = "1" for CPU debugging)

asm
  push     edi
  push     esi
//  cld                // not really needed unless...
//  mov      ax,ds   // why do this at all?
//  mov      ecx,length// not necessary(will be changed to mov ecx,ecx by compiler)
//  mov      esi,ptr1  // could be ,ax (will be changed to mov esi,eax by compiler)
//  mov      edi,ptr2  // could be ,dx (will be changed to mov esi,edx by compiler)
  mov esi,eax
  mov edi,edx
//  mov      es,ax   // not necessary since ds=es
  rep      cmpsb     // repe is replaced by compiler
  mov      eax,1     // Result = True
//  test     ecx,ecx // zf set on ecx = 0
//  jz       @ende   // should be jnz
  jcxz    @ende     // jecxz is replaced by compiler
  dec      eax       // Result = False
  @ende:
  pop      esi
  pop      edi
end;

Hope this helps.
/// John
0
 
LVL 4

Expert Comment

by:erajoj
ID: 1358751
Sorry, didn't see your comment.
If you have other asm-problems, ask them here or mail them to me immediately, and I will try to provide faster answers. One main problem was that I didn't find my 80x86 instruction set reference.
There is a good one at (of course) http://developer.intel.com/design/pentium/manuals/24319101.PDF.
BTW, thanks for the points (can be a lot lower next time)!
/// John
0
 
LVL 2

Author Comment

by:egono
ID: 1358752
the hint with the registry setting is worth all the points - thats what I'm looking for all the time - thx again :-)

0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
ADO Memory leak with DELPHI 2007 37 155
proper way to parse url in delphi 2 134
Delphi TcxGrid group footer summary 3 145
select query - oracle 16 81
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now