Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Swapping 2 bytes

12 views
Skip to first unread message

John

unread,
Jun 11, 2008, 10:32:37 AM6/11/08
to
Hello,

this procedure exchange 2 32bit values :
procedure Swap32(var A, B: TRGBQUAD);
asm
// EAX = [A]
// EDX = [B]
MOV ECX,[EAX] // ECX := [A]
XCHG ECX,[EDX] // ECX <> [B];
MOV [EAX],ECX // [A] := ECX
end;

I mean here A become B and B become A.

How can I do the same for :
procedure Swap8(var A, B: Byte);

Thanks for your help

John

Bob Gonder

unread,
Jun 11, 2008, 11:12:34 AM6/11/08
to
John wrote:

> MOV ECX,[EAX] // ECX := [A]
> XCHG ECX,[EDX] // ECX <> [B];
> MOV [EAX],ECX // [A] := ECX

>How can I do the same for :
>procedure Swap8(var A, B: Byte);

Replace ecx with cl.


Les Pawelczyk

unread,
Jun 11, 2008, 11:49:18 AM6/11/08
to
> this procedure exchange 2 32bit values :
> procedure Swap32(var A, B: TRGBQUAD);
> asm
> // EAX = [A]
> // EDX = [B]
> MOV ECX,[EAX] // ECX := [A]
> XCHG ECX,[EDX] // ECX <> [B];
> MOV [EAX],ECX // [A] := ECX
> end;

The instruction XCHG reg,[mem] is always automatically implementing locking protocol regardless of the presence of LOCK prefix. This
makes it very slow. It is only good for thread and process synchronization.

procedure Swap32(var A, B: LongInt); register;
asm
push [eax]
mov ecx, [edx]
pop [edx]
mov [eax], ecx
end;


> How can I do the same for :
> procedure Swap8(var A, B: Byte);

Unfortunately you cannot do exactly the same for Byte because you cannot PUSH just one byte onto the stack, but there is a better
way:

procedure SwapByte(var A, B: Byte); register;
asm
mov cl, [eax]
mov ch, [edx]
mov [edx], cl
mov [eax], ch
end;

Les.


Sven Pran

unread,
Jun 11, 2008, 6:51:59 PM6/11/08
to

"Les Pawelczyk" <a@b.c> wrote in message
news:484f...@newsgroups.borland.com...

XOR A,B
XOR B,A
XOR A,B

is probably the fastest way to swap A and B

regards Sven

Per Larsen

unread,
Jun 11, 2008, 7:49:58 PM6/11/08
to

"Sven Pran" <no.d...@mail.please> wrote

> XOR A,B
> XOR B,A
> XOR A,B
>
> is probably the fastest way to swap A and B

The coolest, perhaps ;) - but not particularly relevant when the operands
are not in registers.

- Per


John Herbster

unread,
Jun 11, 2008, 9:25:29 PM6/11/08
to

"Sven Pran" wrote

> XOR A,B
> XOR B,A
> XOR A,B

Sven, You beat me to it. Rgds, JohnH

Rudy Velthuis [TeamB]

unread,
Jun 12, 2008, 7:26:02 AM6/12/08
to
John Herbster wrote:

Note that the original was "var A, B", i.e. you get passed pointers to
A and B. In that case, the code Les posted is much better.

--
Rudy Velthuis [TeamB] http://www.teamb.com

"The company doesn't tell me what to say, and I don't tell them
where to stick it." -- Unknown

John

unread,
Jun 12, 2008, 8:57:13 AM6/12/08
to
Great !

Thanks all for your precious help !

Rudy Velthuis [TeamB]

unread,
Jun 12, 2008, 12:54:26 PM6/12/08
to
Wolfgang Ehrhardt wrote:

> And it will not give wrong results as with the xor routine. If you
> call the xor routine with the same variable, ie swap32(a,a), it will
> leave you with a=0.

True.

--
Rudy Velthuis [TeamB] http://www.teamb.com

"Comedy is nothing more than tragedy deferred."
-- Pico Iyer, Time

Wolfgang Ehrhardt

unread,
Jun 12, 2008, 12:39:46 PM6/12/08
to
On Thu, 12 Jun 2008 13:26:02 +0200, "Rudy Velthuis [TeamB]"
<newsg...@rvelthuis.de> wrote:

>John Herbster wrote:
>
>>
>> "Sven Pran" wrote
>> > XOR A,B
>> > XOR B,A
>> > XOR A,B
>>
>> Sven, You beat me to it. Rgds, JohnH
>
>Note that the original was "var A, B", i.e. you get passed pointers to
>A and B. In that case, the code Les posted is much better.
>

And it will not give wrong results as with the xor routine. If you


call the xor routine with the same variable, ie swap32(a,a), it will

leave you with a=0. This can happen for example in a sort routine
where you want to swap two array elements with swap32(a[i], a[j]) and
i=j!

Therefore: Never use the xor swap technique with var parameters!

Wolfgang

--
In order to e-mail me a reply to this message, you will have
to remove PLEASE.REMOVE from the address shown in the header
or get it from http://home.netsurf.de/wolfgang.ehrhardt
(Free open source Crypto, AES, CRC, Hash for Pascal/Delphi)

Aleksandr

unread,
Jun 16, 2008, 1:36:49 AM6/16/08
to
Agreed. But some mod makes the XOR-code working:

procedure Swap32(var A, B: LongInt); register;
asm

mov ecx, [eax]
xor ecx, [edx]
xor [eax], ecx
xor [edx], ecx
end;

procedure TForm1.Button2Click(Sender: TObject);
var
a, b: integer;
begin
a:=$A;
b:=$B;
Swap32(a,b);
ShowMessage(Format('%x %x',[a,b]));
end;

--
regards,
Aleksandr


Rudy Velthuis [TeamB]

unread,
Jun 16, 2008, 7:26:00 AM6/16/08
to
Aleksandr wrote:

> Agreed. But some mod makes the XOR-code working:
>
> procedure Swap32(var A, B: LongInt); register;
> asm
> mov ecx, [eax]
> xor ecx, [edx]
> xor [eax], ecx
> xor [edx], ecx
> end;

Not if A = B, IOW, if you call it with Swap32(A, A);

--
Rudy Velthuis [TeamB] http://www.teamb.com

"Far too many development shops are run by fools who succeed
despite their many failings." -- Brion L. Webster

Thorsten Engler [NexusDB]

unread,
Jun 16, 2008, 10:11:36 AM6/16/08
to
Rudy Velthuis [TeamB] wrote:

> Not if A = B, IOW, if you call it with Swap32(A, A);

Wrong.

In the case of Swap32(A, A):

mov ecx, [eax]
xor ecx, [edx] // ecx is now 0 as any number xor itself is 0
xor [eax], ecx // any number xor 0 remains unchanged, no problem
xor [edx], ecx // any number xor 0 remains unchanged, no problem

You can easily test it:

program Project1;

{$APPTYPE CONSOLE}

uses
SysUtils;

procedure Swap32(var A, B: LongInt); register;
asm
mov ecx, [eax]
xor ecx, [edx]
xor [eax], ecx
xor [edx], ecx
end;

var
a, b: integer;

begin
a:=$76543210;
b:=$89ABCDEF;
WriteLn(Format('%x %x',[a,b]), ' original');
Swap32(a,a);
Swap32(b,b);
WriteLn(Format('%x %x',[a,b]), ' no change');
Swap32(a,b);
WriteLn(Format('%x %x',[a,b]), ' swapped');
Swap32(a,b);
WriteLn(Format('%x %x',[a,b]), ' swapped again');
ReadLn;
end.

--

Bob Gonder

unread,
Jun 16, 2008, 11:06:41 AM6/16/08
to
Rudy Velthuis [TeamB] wrote:
>Aleksandr wrote:
>
>> Agreed. But some mod makes the XOR-code working:
>> procedure Swap32(var A, B: LongInt); register;
>> asm
>> mov ecx, [eax]
>> xor ecx, [edx]
>> xor [eax], ecx
>> xor [edx], ecx
>> end;
>
>Not if A = B, IOW, if you call it with Swap32(A, A);

Why not?
EAX = EDX
mov ecx, [eax] ecx = 'A'
xor ecx, [edx] ecx = 0
xor [eax], ecx [eax] unchanged
xor [edx], ecx [edx] unchanged

Rudy Velthuis [TeamB]

unread,
Jun 16, 2008, 12:09:25 PM6/16/08
to
Bob Gonder wrote:

> Why not?
> EAX = EDX
> mov ecx, [eax] ecx = 'A'
> xor ecx, [edx] ecx = 0
> xor [eax], ecx [eax] unchanged
> xor [edx], ecx [edx] unchanged

OK, got it.

--
Rudy Velthuis [TeamB] http://www.teamb.com

"The backbone of surprise is fusing speed with secrecy."
-- Von Clausewitz (1780-1831)

Aleksandr

unread,
Jun 17, 2008, 2:23:20 AM6/17/08
to
Here is Pascal version, for which compiler produces the same assembler code:

procedure Swap32(var A, B: LongInt);

var
T: LongInt;
begin;
T:=A xor B;
A:=A xor T;
B:=B xor T;
end;

--
regards,
Aleksandr


Uffe Kousgaard

unread,
Jun 17, 2008, 2:36:48 AM6/17/08
to
"Aleksandr" <alsha at mail333 dot com> wrote in message
news:4857584c$1...@newsgroups.borland.com...

>
> procedure Swap32(var A, B: LongInt);
> var
> T: LongInt;
> begin;
> T:=A xor B;
> A:=A xor T;
> B:=B xor T;
> end;

Is that more efficient than:

procedure Swap32(var A, B: LongInt);
var
T: LongInt;
begin;

T:=A;
A:=B;
B:=T;
end;

Regards
Uffe


Aleksandr

unread,
Jun 17, 2008, 2:45:37 AM6/17/08
to
I don't think XOR-code is more efficient.
It's only sample that it can work with VAR-parameters.

--
regards,
Aleksandr


Sven Pran

unread,
Jun 17, 2008, 6:21:12 AM6/17/08
to

"Aleksandr" <alsha at mail333 dot com> wrote in message
news:4857...@newsgroups.borland.com...

>I don't think XOR-code is more efficient.
> It's only sample that it can work with VAR-parameters.

Believeing that I was the one introducing the XOR feature in this thread let
me tell from where i knew this:

In IBM system/360 (mainframe systems) we have an operation XC which actually
performs the XOR process on strings of up to 256 bytes.
This operation is frequently used for zeroing out fields (XC A;A) and also
for swapping fields without any need for temporary storage.

If I remember correct the OP on this thread had a subroutine using register
calling conventions (default in Delphi) which means that the routine:

procedure swap32(A, B: integer);
asm
XOR EAX,EDX
XOR EDX,EAX
XOR EAX,EDX
end;

will always work correct.

regards Sven

Q Correll

unread,
Jun 17, 2008, 1:03:18 PM6/17/08
to
Sven,

| In IBM system/360 (mainframe systems) we have an operation XC...

Wow! You must be another "Ol'timer." <g>

--
Q

06/17/2008 10:02:45

XanaNews Version 1.17.5.7 [Q's Salutation mod]

Aleksandr

unread,
Jun 18, 2008, 4:07:14 AM6/18/08
to
"Sven Pran" :

> In IBM system/360 (mainframe systems) we have an operation XC which
> actually performs the XOR process on strings of up to 256 bytes.

Yes. And there was PL/I the best optimizer IMO.

--
regards,
Aleksandr


jfj

unread,
Jun 18, 2008, 12:01:09 PM6/18/08
to
Hi
for real, double, extended what would be the good formulation?
thanks in advance

Wolfgang Ehrhardt

unread,
Jun 18, 2008, 12:30:27 PM6/18/08
to
On Tue, 17 Jun 2008 12:21:12 +0200, "Sven Pran"
<no.d...@mail.please> wrote:

>procedure swap32(A, B: integer);
>asm
> XOR EAX,EDX
> XOR EDX,EAX
> XOR EAX,EDX
>end;
>
>will always work correct.

Yes. But it is completely useless because it only exchanges the
registers. And

xchg eax, edx

would be another code which does the same useless thing but more
effectively :)

John Herbster

unread,
Jun 18, 2008, 12:58:57 PM6/18/08
to
"jfj" <jf.j...@opales.fr> wrote

> for real, double, extended what would be the good formulation?

Jfj,

Do you mean for swapping between big and little endian?

In-place or to a different destination?

Rgds, JohnH

Rudy Velthuis [TeamB]

unread,
Jun 18, 2008, 4:19:07 PM6/18/08
to
Wolfgang Ehrhardt wrote:

> Yes. But it is completely useless because it only exchanges the
> registers. And
>
> xchg eax, edx
>
> would be another code which does the same useless thing but more
> effectively :)

Did you read the part of the implied LOCK on XCHG in the other messages
of this thread?


--
Rudy Velthuis [TeamB] http://www.teamb.com

"Don't be so humble - you are not that great."
-- Golda Meir (1898-1978) to a visiting diplomat

Per Larsen

unread,
Jun 18, 2008, 5:32:57 PM6/18/08
to

"Rudy Velthuis [TeamB]" <newsg...@rvelthuis.de> wrote in message
news:xn0frl7xf0000...@rvelthuis.de...

>> xchg eax, edx

> Did you read the part of the implied LOCK on XCHG in the other messages
> of this thread?

Doesn't apply to the register-only variant.

- Per


Robert AH Prins

unread,
Jun 18, 2008, 7:45:41 PM6/18/08
to
"Aleksandr" <alsha at mail333 dot com> wrote in message
news:4858...@newsgroups.borland.com...

> "Sven Pran" :
>> In IBM system/360 (mainframe systems) we have an operation XC which
>> actually performs the XOR process on strings of up to 256 bytes.
>
> Yes. And there was PL/I the best optimizer IMO.


Actually, the old (V2.3.0) PL/I compiler was/is pretty bad compared to
most PC stuff, and even the new versions leave a lot to be desired in
some occasions. Worse, they produce almost unreadable assembler listings
that make it pretty hard to see what's actually going on...

Robert (Using PL/I since 1985...)
--
Robert AH Prins
robert dot ah dot prins on gmail


Q Correll

unread,
Jun 18, 2008, 11:48:49 PM6/18/08
to
Robert,

| Robert (Using PL/I since 1985...)

--
Q <quit using PL/1 in 1974>

06/18/2008 20:48:10

Aleksandr

unread,
Jun 19, 2008, 2:55:10 AM6/19/08
to
PL/I & Pl/1 are different compilers.
I think PL/I produces well readable and very optimized assembler listings.
--
regards,
Aleksandr (Using PL/I since 1980)


Robert AH Prins

unread,
Jun 19, 2008, 12:43:55 PM6/19/08
to
"Aleksandr" <alsha at mail333 dot com> wrote in message
news:485a...@newsgroups.borland.com...

> PL/I & Pl/1 are different compilers.

No, there is no language called PL/1.

> I think PL/I produces well readable and very optimized assembler
> listings.

About which PL/I compiler are we talking? As I wrote, the V2.3.0
assembler listings are readable (provided you use the 'lc(N)' compiler
option, with N>= 100), the assembler listing of the Enterprise PL/I
compiler, excusez-le-mot, stink, and unlike the V2.3.0 listings, there's
virtually no trace of any of the PL/I varaables to be found anymore.

As for optimisation, the V2.3.0 compiler is absolutely terrible in many
ways - I once reduced the CPU time of a program from 3 hours to 20
minutes by changing just a single statement. As this was with a former
client, I don't know how the V3R7M0 compiler would handle it. However,
the latter will generate complete crap code for a 'BY NAME' assignment,
where the destination is BASED.

Finally, the Enterprise Compiler cannot even handle all programs the
V2.3.0 compiler could compile, try this little gem (as it's likely to
wrap, I've added $$$ to the start and end of each line)

$$$%dcl z%z='put edit';proc options(main;q=''''put list(m;do
i=1,2;z(q)skip;do j=$$$
$$$1to 78c=substr(m(i),j;if c=q
z(c;z(c;end;z(q',';dcl(c,q)char,m(2)char(99)init($$$
$$$'%dcl z%z=''put edit'';proc options(main;q=''''''''put list(m;do
i=1,2;z(q)skip;do j=',$$$
$$$'1to 78c=substr(m(i),j;if c=q
z(c;z(c;end;z(q'','';dcl(c,q)char,m(2)char(99)init(',$$$

Robert

Eriks Aleksans

unread,
Jun 19, 2008, 12:51:09 PM6/19/08
to
> $$$%dcl z%z='put edit';proc options(main;q=''''put list(m;do
> i=1,2;z(q)skip;do j=$$$
> $$$1to 78c=substr(m(i),j;if c=q
> z(c;z(c;end;z(q',';dcl(c,q)char,m(2)char(99)init($$$
> $$$'%dcl z%z=''put edit'';proc options(main;q=''''''''put list(m;do
> i=1,2;z(q)skip;do j=',$$$
> $$$'1to 78c=substr(m(i),j;if c=q
> z(c;z(c;end;z(q'','';dcl(c,q)char,m(2)char(99)init(',$$$
>
> Robert

Could you, please, translate this to Delphi? Just for fun ;-)

Eriks

Q Correll

unread,
Jun 19, 2008, 1:10:26 PM6/19/08
to
Robert,

| No, there is no language called PL/1.

Yes there is. It's the same language as PL/I. Both acronyms have been
routinely and interchangeably used for forty years. <g> (A quick
Google will show that they still refer to the same language.)

--
Q

06/19/2008 10:07:28

Robert AH Prins

unread,
Jun 19, 2008, 5:28:25 PM6/19/08
to
"Eriks Aleksans" <n...@email.com> wrote in message
news:485a...@newsgroups.borland.com...


Take your pick from any of these
http://www.nyx.net/~gthompso/self_pasc.txt

It's a quine, and what more, it's the smallest possible quine in PL/I
using the IBM V2.3.0 compiler (with some pretty non-standard compiler
options) The program throws a load of errors that would make any other
compiler give up, but miraculously, it also produces correctly working
code! It does not compile with the new and shiny Enterprise Compilers...

Aleksandr

unread,
Jun 20, 2008, 6:13:05 AM6/20/08
to
>> "Aleksandr":

>> PL/I & Pl/1 are different compilers.


> "Robert AH Prins":


> No, there is no language called PL/1.

PL/I was developed by IBM as part of the development of OS/360.
IBM OS/360 has two PL/I compilers: PL/1 F-compiler (pgm=IEMAA) and
PL/I optimizer.

>> I think PL/I produces well readable and very optimized assembler
>> listings.

> About which PL/I compiler are we talking?

I am about second one.

> $$$%dcl z%z='put edit';proc options(main;q=''''put list(m;do
> i=1,2;z(q)skip;do j=$$$
> $$$1to 78c=substr(m(i),j;if c=q
> z(c;z(c;end;z(q',';dcl(c,q)char,m(2)char(99)init($$$
> $$$'%dcl z%z=''put edit'';proc options(main;q=''''''''put list(m;do
> i=1,2;z(q)skip;do j=',$$$
> $$$'1to 78c=substr(m(i),j;if c=q
> z(c;z(c;end;z(q'','';dcl(c,q)char,m(2)char(99)init(',$$$

I wrote my PL/I programs in Pascal style without any problem.

--
regards,
Aleksandr


0 new messages