PowerBASIC Forums
  PowerBASIC for Windows
  XOR every byte in a string using inline ASM? (Page 1)

Post New Topic  Post A Reply
profile | register | preferences | faq | search

UBBFriend: Email This Page to Someone!
This topic is 2 pages long:   1  2 
next newest topic | next oldest topic
Author Topic:   XOR every byte in a string using inline ASM?
Wayne Diamond
Member
posted March 05, 2002 12:24 AM     Click Here to See the Profile for Wayne Diamond     Edit/Delete Message   Reply w/Quote
Dim sStr As String
Dim I As Long
For I = 1 To Len(sStr)
MID$(sStr, I, 1) = CHR$(ASC(MID$(sStr, I, 1)) XOR 50)
Next I

Would anyone be kind enough to convert this to inline assembly? I need maximum speed for large files!
Im a huge fan of assembly but this is still a bit out of my reach at the moment, still much study to do

------------------

IP: Logged

Lothar Pink 2
unregistered
posted March 05, 2002 12:48 AM           Edit/Delete Message   Reply w/Quote
NOT TESTED haven't got PB at work ...


myStrLen& = LEN(myStr)

! mov eax, myStr ; string descriptor in eax
! cmp eax, 0 ; no str data
! je EndXorLoop

! mov ecx, myStrLen&
BeginXorLoop
! mov eax, [eax] ; eax now is the pointer to the string data
! mov dl, [eax] ; move 1 byte to dl (low byte of edx)
! xor dl, 50
! mov [eax], dl
! dec ecx
! cmp ecx, 0 ; detect end of string
! je EndXorLoop
! jmp BeginXorLoop

EndXorLoop:

If it doesn't work, tell me what error occurs. If a GPF occurs, run
it through the debugger ...

Best Regards
Lothar

------------------

IP: Logged

Wayne Diamond
Member
posted March 05, 2002 12:51 AM     Click Here to See the Profile for Wayne Diamond     Edit/Delete Message   Reply w/Quote
quote:
Originally posted by Lothar Pink 2:
NOT TESTED haven't got PB at work ...

Hmm dont you think its time to find a new line of work then?

Thanks very much Lothar! It looks spot on, I'll give it a go now and report my findings here in about 10-15 minutes

------------------

IP: Logged

Lothar Pink 2
unregistered
posted March 05, 2002 12:54 AM           Edit/Delete Message   Reply w/Quote
BTW, there's a wonderful ASM documentation at intel.com, I don't know
where but I've downloaded it some time ago, and printed it (about 400 pages...)

Assembler is very easy because only a few statements are needed for
most tasks, and it's very easy to debug. It's more logical thought than
programming skills that count ...

L.

------------------

IP: Logged

Lothar Pink 2
unregistered
posted March 05, 2002 12:56 AM           Edit/Delete Message   Reply w/Quote
I'm working at a press agenture, it's not really programming / PC related.

Lothar

------------------

IP: Logged

Wayne Diamond
Member
posted March 05, 2002 12:59 AM     Click Here to See the Profile for Wayne Diamond     Edit/Delete Message   Reply w/Quote
Lothar, I just had to add a ":" to the end of BeginXorLoop to make it a label, and then she compiled fine.
But it GPF'd at this line:
! mov dl, [eax]
Any idea why?
Thanks

And yes, I want to learn assembler just for string and number manipulation, it seems to be often a lot easier (and nearly always faster) when done in asm!

------------------

IP: Logged

Lothar Pink 2
unregistered
posted March 05, 2002 01:05 AM           Edit/Delete Message   Reply w/Quote
Ooops...


myStrLen& = LEN(myStr)

! mov eax, myStr ; string descriptor in eax
! cmp eax, 0 ; no str data
! je EndXorLoop

! mov ecx, myStrLen&
BeginXorLoop:
! mov dl, [eax] ; move 1 byte to dl (low byte of edx)
! xor dl, 50
! mov [eax], dl
! dec ecx
! cmp ecx, 0 ; detect end of string
! je EndXorLoop
! inc eax
! jmp BeginXorLoop

EndXorLoop:

I'm sorry ...

------------------

(!!! two lines have been edited, copy the whole source again !!!)


[This message has been edited by Lothar Pink 2 (edited March 05, 2002).]

IP: Logged

Wayne Diamond
Member
posted March 05, 2002 01:20 AM     Click Here to See the Profile for Wayne Diamond     Edit/Delete Message   Reply w/Quote
PERFECT! Thankyou so very much
These sorts of things may seem simple to people like yourself who are already asm-fluent, but as im not fluent, I find these sorts of samples the best to learn from
I'm sure others will get some use out of this!

Best,
Wayne

------------------

IP: Logged

Lothar Pink 2
unregistered
posted March 05, 2002 01:21 AM           Edit/Delete Message   Reply w/Quote
Well, all you have to know about asm, are the processor registers,
the mov statement, the jmp statement and it's derivations (in combination
with "cmp"), and the arithmetic statements (add, mul, dec, inc, ...)

I forgot push/pop.

It's very easy!

Lothar

------------------

[This message has been edited by Lothar Pink 2 (edited March 05, 2002).]

IP: Logged

Wayne Diamond
Member
posted March 05, 2002 01:43 AM     Click Here to See the Profile for Wayne Diamond     Edit/Delete Message   Reply w/Quote
Lothar, its _too_ simple, thats probably where I get confused, thinking that something should be more complex than it really is
Ive just been reading through your code now for the last 10 or so minutes, and I cant see any way that it could be optimised, at least I cant see any code that could be taken out or made faster... would you say this is about as fast as such an XOR loop could get?
Thanks i love this sorta stuff!

------------------

IP: Logged

Lothar Pink 2
unregistered
posted March 05, 2002 01:48 AM           Edit/Delete Message   Reply w/Quote
Well, when dealing with large strings, it would be faster to load 32 bit
junks into edx, instead of loading 1-byte-junks into dl...

However, the string lenght MUST be a multiple of 4 then ...


myStrLen4& = LEN(myStr) \ 4 ' we are working with 4-byte-junks now...

! mov eax, myStr ; string descriptor in eax
! cmp eax, 0 ; no str data
! je EndXorLoop

! mov ecx, myStrLen4&
BeginXorLoop:
! mov edx, [eax] ; move 4 bytes to edx
! xor edx, 50
! mov [eax], edx
! dec ecx
! cmp ecx, 0 ; detect end of string
! je EndXorLoop
! add eax, 4
! jmp BeginXorLoop

EndXorLoop:

l.

------------------

CAUTION: small bug corrected ...

[This message has been edited by Lothar Pink 2 (edited March 05, 2002).]

IP: Logged

Lothar Pink 2
unregistered
posted March 05, 2002 01:53 AM           Edit/Delete Message   Reply w/Quote
In case you don't know, a register is a "variable" inside the procesor.

A register also is a "pointer". To access the value of EAX, just write
EAX. To access the value of the memory address stored in EAX, use
[EAX].

So, PB ebx = eax would be
! mov ebx, eax

and PB ebx = @eax would be
! mov ebx, [eax]

This always moves 32-bit-chunks into the registers.
In order to move 16 bits, write
! mov bx, [eax]

and in order to move 8 bits (1 byte), write
! mov bl, [eax]

al, bl, cl, dl are 8-byte-registers which are part of eax, ...
ax, bx, dx, dx are 16-byte ...

In order to understand the code, you also need do know what "cmp" is...
it just compares two values.
The jxxx statement after the cmp statements is a conditional jump.
"je" means "jump if equal"
there are also "ja" (above), "jb" (below), "jae" jump above or equal ...
statements, as well as an extra set of "jxxx" statements for signed
integers.

Lothar


[This message has been edited by Lothar Pink 2 (edited March 05, 2002).]

IP: Logged

Wayne Diamond
Member
posted March 05, 2002 02:05 AM     Click Here to See the Profile for Wayne Diamond     Edit/Delete Message   Reply w/Quote
Superb thanks, Im looking through your last two posts now
Incidently, I did a GetTickCount speed test using a 50mb string ("mystr = STRING$(50000000,0)")
Using the normal BASIC-code version of the XOR loop that I posted at the very top of this thread, that clocked in at 31625 'ticks'. Your assembly version did it in 485

------------------

IP: Logged

Lothar Pink 2
unregistered
posted March 05, 2002 02:10 AM           Edit/Delete Message   Reply w/Quote
Actually, a LOT of optimization can also be done in PB code, using pointers
(they are VERY fast!!!)

You might also test the following code:


LOCAL pStr AS BYTE PTR

pStr = STRPTR(myStr)

FOR z& = 0 TO LEN(myStr)
@pStr = XOR(@pStr)
INCR pStr

NEXT z&

As well as the following code for 4-byte-XOR...


LOCAL pStr AS LONG PTR

pStr = STRPTR(myStr)

FOR z& = 0 TO LEN(myStr) \ 4
@pStr = XOR(@pStr)
pStr = pStr + 4

NEXT z&

The disadvantage of your code is that it allocates and frees memory
on every loop iteration ...

Lothar

------------------

IP: Logged

Steve Hutchesson
Member
posted March 05, 2002 02:41 AM     Click Here to See the Profile for Steve Hutchesson     Edit/Delete Message   Reply w/Quote
Wayne,

If I remember correctly I posted this algo a long time ago and its
the code for XOR based encryption using any length key up to the
source length. I think the technique is called a "one shot pad" so
if you want a bit more grunt than a 1 character XOR, this one should
help some.

The problem with a single character XOR is that you can break the
encryption in 256 or less combinations. The more characters you use,
the more complex it becomes to break it.

SPeed should be reasonable allowing that it handles the sequential
reading of the key string as well.

Regards,

hutch@movsd.com

PS : I think you can remove the 3 register preservations at the beginning
and end as PB does this automatically. Kust comment them out and give it
a whirl.


' ###########################################################################

FUNCTION XorString(bString$,KeyString$) as LONG

' ---------------------------------------------------------------
' The method used is to read through the source string "bString$"
' one byte at a time and XOR it with the "KeyString$" which is
' also read one byte at a time. If the Keystring is shorter than
' the source string, it will loop around to the beginning of the
' keystring and continue the same process until the source string
' is completed.
' ---------------------------------------------------------------

#REGISTER NONE

LOCAL ln as LONG ' source length
LOCAL lkey as LONG ' key length
LOCAL lref as LONG ' counter reference for key char position
LOCAL src as LONG
LOCAL lpBt as LONG
LOCAL pcnt as LONG
LOCAL bvar as BYTE

! push ebx
! push esi
! push edi

ln = len(bString$)
lkey = len(KeyString$)

lpBt = StrPtr(KeyString$) ' get starting address of key string
pcnt = lpBt ' copy it to another variable
lref = pcnt + lkey

! mov esi, lpBt
! mov al,[esi]
! mov bvar, al ; put 1st byte in bvar

src = StrPtr(bString$)

! mov ecx, ln
! mov esi, src
! mov edi, src

xsSt:
! mov al,[esi] ; copy 1st byte of source into al
! inc esi

! xor al, bvar ; xor al with the byte in bvar

! push eax
! push esi

' ====== This code gets the next byte in the key string ======
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! inc pcnt ; increment byte address
! mov esi, pcnt ; put it in esi
! mov al,[esi]
! inc esi

! mov ebx, lref
! cmp pcnt, ebx ; if pcnt = lref
! jne xsNxt

! mov edx, lpBt
! mov pcnt, edx ; reset pcnt to ariginal address
! mov esi, pcnt ; put original address in esi

! mov al,[esi]
! inc esi

xsNxt:
! mov bvar, al ; put the next byte in the variable
' ============================================================

! pop esi
! pop eax

! mov [edi], al
! inc edi

! dec ecx
! cmp ecx, 0
! jne xsSt

! pop edi
! pop esi
! pop ebx

FUNCTION = 0

END FUNCTION

' ###########################################################################

------------------

IP: Logged


This topic is 2 pages long:   1  2 

All times are EasternTime (US)

next newest topic | next oldest topic

Administrative Options: Close Topic | Archive/Move | Delete Topic
Post New Topic  Post A Reply
Hop to:

Contact Us | PowerBASIC BASIC Compilers

Copyright © 1999-2007 PowerBASIC, Inc. All Rights Reserved.


Ultimate Bulletin Board 5.45c