|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
tanjiajun_34 Grandmaster Cheater Reputation: 0
Joined: 16 Feb 2006 Posts: 786 Location: Singapore
|
Posted: Tue Oct 19, 2010 8:45 am Post subject: C Programming question |
|
|
I just started it so sorry if I ask way too stupid question.
I just want it to compare if the inputted text is "testing", if it is it will show the "YEAH!". But it just did not show when I type "testing".
Code: | #include <stdio.h>
void main()
{
int i;
char str[30];
while (i<10000)
{
scanf("%s",str);
if (str=="testing")
{
printf("YEAH!");
}
}
}
|
|
|
Back to top |
|
|
Slugsnack Grandmaster Cheater Supreme Reputation: 71
Joined: 24 Jan 2007 Posts: 1857
|
Posted: Tue Oct 19, 2010 9:02 am Post subject: |
|
|
In C, strings can not be compared directly. The x86 instruction set only allows direct comparison of byte/word/dword values. Since your string is 8 bytes ( including null terminator ) you will have to use a string comparison algorithm.
There are plenty out there, the most common one being strcmp(). Or even better if you are doing Windows programming _tscmp().
|
|
Back to top |
|
|
KernelMode How do I cheat? Reputation: 1
Joined: 13 Oct 2010 Posts: 9 Location: Messing around with bits in you kernel for now...
|
Posted: Tue Oct 19, 2010 11:40 am Post subject: |
|
|
Yes like Slugsnack said you can't just compare all the bytes of something at once. It's just how it works, its not just with strings. On 32-bit, a DWORD/4 bytes/32-bit value is the largest amount of data that can be read or written in a single instruction. On 64-bit, the largest is you guessed it, 8 bytes/64-bits.
For example, to copy some memory from one place to another, we can't just say tada! and the memory is copied. No... Instead the memory is moved say a dword at a time until all memory we wanted is copied. Little small operations on bytes, words, and double words, repeated many times form bigger, more complex operations.
A function like strcmp() goes though and compares each byte of the first string to each byte of the second string, and returns 0 if they are equal. _stricmp() for case insensitive searches.
so...
Code: |
if(strcmp(str, "testing") == 0)
{
printf("YEAH!");
}
|
We can make our own simple string comparison functions to better understand whats going on... Note: For my string compare functions below I return 1 if they are the same and 0 if they are not, which is unlike the normal string comparison functions.
Case-sensitive compare:
Code: |
int StringComp(char *FirstString, char *SecondString)
{
int i = 0;
while(FirstString[i] != 0) //while we haven't reached the end of the first string
{
if(FirstString[i] != SecondString[i]) //if current byte of first string doesn't equal current byte of second
return 0;
i++;
}
//if we made it here, past the while loop, then...
//the second string is the same as the first string for as long as the first string is...
//if the second string is longer, but all characters have been the same up to the last character of the first string
//well thats what the next line is for ;)
if(SecondString[i] == 0) //second string is at the end as well so its a match
return 1;
else
return 0;
}
|
Case-insensitive compare:
Code: |
int StringIComp(char *FirstString, char *SecondString)
{
int i = 0;
char singlecharacter, switchcaseletter;
while(FirstString[i] != 0)
{
singlecharacter = SecondString[i];
//this translates to english as..."If singlecharacter is an uppercase alphabetical character or if singlecharacter is a lowercase alphabetical character"
if(singlecharacter >= 0x41 && singlecharacter <= 0x5A || singlecharacter >= 0x61 && singlecharacter <= 0x7A)
{
switchcaseletter = singlecharacter ^ 0x20; //xor'ing a letter with 0x20 switches the letter from uppercase to lowercase/vice versa
if(FirstString[i] != singlecharacter && FirstString[i] != switchcaseletter)
return 0;
}
else
{
//character is not alphabetical so don't inverse the case (since it's not a letter of the alphabet, that will screw it up)
if(FirstString[i] != singlecharacter)
return 0;
}
i++;
}
if(SecondString[i] == 0) //second string is at the end as well so its a match
return 1;
else
return 0;
}
|
Usage:
Code: |
char *str = "Hello World!";
if(StringComp(str, "Hello World!") == 1)
{
//a match
}
if(StringIComp(str, "hEllO wOrLd!") == 1)
{
//a match
}
|
It's probably best to stick with using the string compare's your given... This was just meant for educational purposes...
However if you ever needed your string comparison to be faster, and you've debugged your program and found it to be slow, some custom written assembler string comparison functions just might speed it up a bit Not that those are assembler (clearly they are C++ written) but could easily be made into assembler (Given that you know assembler of course).
|
|
Back to top |
|
|
Slugsnack Grandmaster Cheater Supreme Reputation: 71
Joined: 24 Jan 2007 Posts: 1857
|
Posted: Tue Oct 19, 2010 12:42 pm Post subject: |
|
|
Another thing. You are making a conceptual error by comparing str to a string. str is not a string. str is simply a pointer. It just so happens that it points to a set of bytes representing a string. If the value you want to check is 4 bytes or less it is actually possible to compare by value instead of using an algorithm.
|
|
Back to top |
|
|
hcavolsdsadgadsg I'm a spammer Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Tue Oct 19, 2010 1:53 pm Post subject: |
|
|
KernelMode wrote: | Yes like Slugsnack said you can't just compare all the bytes of something at once. It's just how it works, its not just with strings. On 32-bit, a DWORD/4 bytes/32-bit value is the largest amount of data that can be read or written in a single instruction. On 64-bit, the largest is you guessed it, 8 bytes/64-bits. |
what about SSE?
movaps is a single instruction :V
|
|
Back to top |
|
|
KernelMode How do I cheat? Reputation: 1
Joined: 13 Oct 2010 Posts: 9 Location: Messing around with bits in you kernel for now...
|
Posted: Tue Oct 19, 2010 4:57 pm Post subject: |
|
|
slovach wrote: | KernelMode wrote: | Yes like Slugsnack said you can't just compare all the bytes of something at once. It's just how it works, its not just with strings. On 32-bit, a DWORD/4 bytes/32-bit value is the largest amount of data that can be read or written in a single instruction. On 64-bit, the largest is you guessed it, 8 bytes/64-bits. |
what about SSE?
movaps is a single instruction :V |
Ah yes, the xmm registers and accompanying instructions. I was forgetting about those. So I think my statement is wrong. Maybe I should change it to "On a 32-bit OS, 32-bits/4 bytes is the largest size of data that can be read or written at one time."
Getting rid of the "in a single instruction" part should make it technically correct.
However it still may be wrong... It all depends on how those instructions that deal with more than 32-bits conduct their business. Do they actually do their magic in one swift operation? Or do the instructions themselves do a few mini operations to achieve the result? It gets more confusing the more I think about it, but I would just like to be clear about this.
Well whether my new statement is correct or not, we can't deny the inherent limitation of 32-bit!
I've never used the movaps or movups instructions before, but I attempted messing around with it and CE just now. For some reason I couldn't get it to assemble any instruction that would movaps/movups from an xmm register back into my memory location. (I may have discovered a bug in CE) even adding an 'xmmword ptr' keyword doesn't seem to help. I don't think CE even recognizes that keyword as "movups xmm0,[eax]" failed to assemble also when adding it like "movups xmm0, xmmword ptr [eax]"
Code: |
alloc(InstructionTest, 128)
alloc(OneTwentyEightBits, 16)
registersymbol(OneTwentyEightBits)
OneTwentyEightBits:
dd 00000001
dd 00000002
dd 00000003
dd 00000004
InstructionTest:
lea eax,[OneTwentyEightBits]
xorps xmm0,xmm0 //clear xmm0 register
movups xmm0,[eax] //mov four 32-bit values in one instruction
//xmm0 currently: 00000001 - 00000002 - 00000003 - 00000004
shufps xmm0,xmm0,93 //after: 00000004 - 00000001 - 00000002 - 00000003
shufps xmm0,xmm0,93 //after: 00000003 - 00000004 - 00000001 - 00000002
shufps xmm0,xmm0,93 //after: 00000002 - 00000003 - 00000004 - 00000001
shufps xmm0,xmm0,93 //after: back where we started
//xmm0 currently: 00000001 - 00000002 - 00000003 - 00000004
//movups [eax],xmm0 //for some reason this wont assemble
ret
|
Since I couldn't get that instruction to compile (thats what I was going to use to see changes) I instead neglected adding a createthread line and just injected and set a breakpoint and manually created the thread. That let me see the values in the xmm0 register, but all in all what good is this if I can't get the value back out of the register! I think doing a db to define the bytes of the instruction would probably work, but CE should really be able to assemble it!
EDIT: As it seems it is actually a bug, a workaround as Dark Byte described is to use the same first instruction then manually change the second byte of it before it executes. You can either edit the byte manually by hand or I chose to put it in the script. By adding a label 'MoveBackInst' right above the instruction, I avoided having to count the bytes leading up to it. I find it better that way as any code added/removed from between the two movups instructions wont effect anything and I wont have to be recounting bytes after each change.
Code: |
alloc(InstructionTest, 64)
alloc(OneTwentyEightBits, 16)
registersymbol(OneTwentyEightBits)
label(MoveBackInst)
OneTwentyEightBits:
dd 00000001
dd 00000002
dd 00000003
dd 00000004
InstructionTest:
mov byte ptr [MoveBackInst+1],11
lea eax,[OneTwentyEightBits]
xorps xmm0,xmm0 //clear xmm0 register
movups xmm0,[eax]
shufps xmm0,xmm0,93
shufps xmm0,xmm0,93
shufps xmm0,xmm0,93
shufps xmm0,xmm0,93
MoveBackInst:
movups xmm0,[eax]
ret
|
Description: |
After first instruction is executed the instruction of interest is modified. |
|
Filesize: |
59.39 KB |
Viewed: |
17702 Time(s) |
|
Last edited by KernelMode on Wed Oct 20, 2010 5:09 am; edited 1 time in total |
|
Back to top |
|
|
hcavolsdsadgadsg I'm a spammer Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Tue Oct 19, 2010 6:40 pm Post subject: |
|
|
packed instructions are effectively done in one shot.
|
|
Back to top |
|
|
Slugsnack Grandmaster Cheater Supreme Reputation: 71
Joined: 24 Jan 2007 Posts: 1857
|
Posted: Tue Oct 19, 2010 6:56 pm Post subject: |
|
|
KernelMode: The x86 instruction set is sort of screwed up and very inconsistent. It is neither RISC nor CISC, it is some weird mixture of both. The other inconsistencies of x86 make it an architectural nightmare. For this reason, it is not all that useful to care the definition when you speak of 'one instruction' in this context. For even more confusion and inconsistency look into 'macro instructions' such as scasb/w/d or random instructions like jecxz, etc.
To answer your question:
Quote: | Do they actually do their magic in one swift operation? |
It completely depends on your definition of an 'operation'. Do you mean one cycle ? Are you bearing in mind pipelining ?
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25302 Location: The netherlands
|
Posted: Tue Oct 19, 2010 7:36 pm Post subject: |
|
|
Looks like a bug in ce 5.6.1
anyhow, use the movups xmm,[address] and then change the second byte from 10 to 11 for the reverse operation
e.g:
movups xmm1,[rax]=0f 10 08
so
movups [rax],xmm1=0f 11 08
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
KernelMode How do I cheat? Reputation: 1
Joined: 13 Oct 2010 Posts: 9 Location: Messing around with bits in you kernel for now...
|
Posted: Wed Oct 20, 2010 5:40 am Post subject: |
|
|
Thanks Dark Byte! Using the same instruction then modifying the one byte does the trick!
Slugsnack: You're right its better to not care too much in the technical details of it. It is what is it is I guess!
In case anyone else wanted to play around with the movaps/movups instructions and didn't get what Dark Byte means, I edited my post above to show an example.
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|