Welcome to Tech Support Forum home to more then 136,000 problems solved. Issues have included: Spyware, Malware, Virus Issues, Windows, Microsoft, Linux, Networking, Security, Hardware, and Gaming Getting your problem solved is as easy as:
1. Registering for a free account
2. Asking your question
3. Receiving an answer

Registered members:
* Get free support
* Communicate privately with other members (PM).
* Removal of this message
* See fewer ads.
* And much more..

 



Want to know how to post a question? click here Having problems with spyware and pop-ups? First Steps
Go Back   Tech Support Forum > The IT Pro > Programming
User Name
Password
Site Map Register Donate Rules Blogs Mark Forums Read


Programming A discussion forum for programs and programming used in tech-related businesses.

Reply
 
LinkBack Thread Tools
Old 01-02-2007, 06:18 AM   #1 (permalink)
Registered User
 
Join Date: Nov 2006
Location: Sydney, Australia
Posts: 207
OS: WinXP-Home


Send a message via MSN to MattBro
Few handy routines.

Just a few general-purpose I wrote for a project which I thought I'd share.

NOTE: Requires an x86/x64-based processor. (This includes AMD, and many others).

Code:
/*
 * Utility.cpp
 * ===========
 * Copyright (C) Matthew J. W.
 * Version 1.0
 *
 *
 * Description:
 *   Implementation of the Utility module.
 *
 *
 * Abstract:
 *   The Utility module covers routines which are of a strictly general-purpose
 *   nature.
 *
 *
 *******************************************************************************************************************************************************/
#include "BnetDiagTool.h"




////////////////////////////////////////////////////////////////////////////
//
// Math Functions
//
////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------
// Dword PowerOf(Dword, Dword)
// -=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// Description:
//   Calculates a base raised to a certain power.
//
//
// Parameters:
//   [Dword] 'dwBase'     - Base being raised.
//   [Dword] 'dwExponent' - Power the base is being raised to.
//
//
// Return Value:
//   Returns 'dwBase' raised to the power of 'dwExponent'.
//
//
Dword __fastcall PowerOf(Dword dwBase, Dword dwExponent)
{
	__asm
	{
		/*
         * ECX - Base.
		 * EBX - Exponent.
		 * EAX - Result.
		 *
		 */

		// Save registers we'll be using, to ensure we don't interfer with the
		// caller. Also save operation flags.
		pushfd
		push ecx
		push ebx
		push edx
		

		// Initialize.
		mov ebx, edx
		xor edx, edx
		mov eax, 1

		// If we have no exponent, the result is always 1.
		cmp ebx, 0
		je EXIT

		RAISE_POWER:
			// Raise the base.
			mul ecx
			dec ebx

			// Have we raised to the appropiate power?
			cmp ebx, 0
			jne RAISE_POWER

		EXIT:
			// Return original registers, and operation flags.
			pop edx
			pop ebx
			pop ecx
			popfd

	}
}
			


////////////////////////////////////////////////////////////////////////////
//
// String Functions
//
////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------
// Dword GetStringLength(Char*)
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=
//
// Description:
//   Retrieves the length of a null-terminated, ascii string.
//
//
// Parameters:
//   [Char*] 'pstr' - The string in question.
//
//
// Return Value:
//   Returns the length of 'pstr'.
//
//
Dword __fastcall GetStringLength(const Char* pstr)
{
	__asm
	{
		/*
         * ECX - Pointer to the string.
		 * EAX - Buffer for blocks read from the string.
		 * EBX - Pointer to the first element of the string.
		 *
		 */

		// Save registers we'll be using, to ensure we don't interfer with the
		// caller. Also save operation flags.
		pushfd
		push ecx
		push ebx

		// Remember the starting address of the string.
		mov ebx, ecx

		READ_BLOCK:
			// Read a 4-byte block of the string.
			mov eax, dword ptr [ecx]

			// Is byte-0 the terminator?
			test eax, 0x000000FF
			jz FOUND_NULL

			// Is byte-1 the terminator?
			test eax, 0x0000FF00
			jz FOUND_NULL

			// Is byte-2 the terminator?
			test eax, 0x00FF0000
			jz FOUND_NULL

			// Is byte-3 the terminator?
			test eax, 0xFF000000
			jz FOUND_NULL

			// Move on to the next block.
			add ecx, 4
			jmp READ_BLOCK

		FOUND_NULL:
			/* 
			 * Now that we've found the block which contains the null-terminator, it's time
			 * to figure out which exact byte is the terminator itself.
			 * Keeping in mind, if the first three bytes are _not_ null, then the fourth
			 * byte _must_ be.
			 *
			 */
			test eax, 0x000000FF
			jz EXIT
			inc ecx

			test eax, 0x0000FF00
			jz EXIT
			inc ecx

			test eax, 0x00FF0000
			jz EXIT
			inc ecx


		EXIT:
			// To calculate the length of the string, we find the difference between
			// it's starting address(EBX) and the address of the null-terminator(ECX).
			sub ecx, ebx
			mov eax, ecx

			// Return original registers, and operation flags.
			pop ebx
			pop ecx
			popfd
	}
}



//--------------------------------------------------------------------------
// Byte CharToInt(Char)
// -=-=-=-=-=-=-=-=-=-=
//
// Description:
//   Converts a ascii-character to an integer.
//
//
// Parameters:
//   [Char] 'c' - The character to be converted.
//
//
// Return Value:
//   Returns the binary integer of which 'c' represents.
//
//
// Notes:
//   # Only the binary, octal, decimal and hexadecimal number-systems are supported.
//   # The result is undefined if an improper value is given.
//
//
Byte __fastcall CharToInt(Char c)
{
	__asm
	{
		/*
         * CL - The character being converted.
		 *
		 */

		// Is the character _not_ of the binary, octal or decimal systems?
		cmp cl, 0x39
		jg HEXADECIMAL

		// Binary, octal or decimal.
		sub cl, 0x30
		jmp EXIT

		HEXADECIMAL:
			// Are we dealing with a lower-case hex-digit?
			cmp cl, 0x46
			jg LOWER_CASE_HEX

			// Upper-case hexadecimal.
			sub cl, 0x37
			jmp EXIT

			LOWER_CASE_HEX:
				// Lower-case hexadecimal.
			sub cl, 0x57

		EXIT:
			mov al, cl
	}
}



//--------------------------------------------------------------------------
// Char IntToChar(Byte)
// -=-=-=-=-=-=-=-=-=-=
//
// Description:
//   Converts a binary integer to an ascii-character.
//
//
// Parameters:
//   [Byte] 'b' - The integer to be converted.
//
//
// Return Value:
//   Returns the character representation of 'b'.
//
//
// Notes:
//   # Only the binary, octal, decimal and hexadecimal number-systems are supported.
//   # The result is undefined if an improper value is given.
//   # Hexadecimal digits are always outputted in upper-case form.
//
//
Char __fastcall IntToChar(Byte b)
{
	__asm
	{
		/*
         * CL - The integer being converted.
		 *
		 */

		// Is the integer _not_ part of the binary, octal or decimal systems?
		cmp cl, 0x9
		jg HEXADECIMAL

		// Binary, octal or decimal.
		add cl, 0x30
		jmp EXIT

		HEXADECIMAL:
			// Hexadecimal.
			add cl, 0x37

		EXIT:
			mov al, cl
	}
}



//--------------------------------------------------------------------------
// Dword StrToInt(Char*, Dword)
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=
//
// Description:
//   Converts a string of characters representing a number to an actual binary
//   integer.
//
//
// Parameters:
//   [Char*] 'pstr'   - The string to be converted.
//   [Dword] 'dwBase' - The base system in which the string should be interpreted as.
//
//
// Return Value:
//   Returns the integer representation of 'pstr'.
//
//
Dword __fastcall StrToInt(const Char* pstr, Dword dwBase)
{
	__asm
	{
		/*
         * ECX - Pointer to the number string ('pstr').
		 * ESI - The base system ('dwBase').
		 * EBX - Current positional value.
		 * EDI - Stores (accumulatively) the binary integer result.
		 *
		 */

		// Save registers we'll be using, to ensure we don't interfer with the
		// caller. Also save operation flags.
		pushfd
		push ebx
		push ecx
		push edx
		push esi
		push edi
		push ebp

		// EDX ('dwBase') will be stored in ESI to avoid algorithm conflict.
		mov esi, edx

		/*
		 * Before we can begin converting the string, we must calculate the positional
		 * value of the left-most digit. This will enable us to able to convert the
		 * string left-to-right, hence from the first string element, to the last.
		 *
		 * The algorithm for retrieving the positional-value is simple, raise the
		 * base system by the length of the string (minus one).
		 *
		 */

		 // First step, get the length of the string.
		 call GetStringLength 
		 dec eax

		 // Temporarily store the string pointer in EDI.
		 mov edi, ecx

		 // Calculate the left-most digit's positional value.
		 mov ecx, esi // 'dwBase'
		 mov edx, eax // 'dwExponent'
		 call PowerOf

		 // Store the positional-value in EBX.
		 mov ebx, eax

		 // Return the string pointer to it's proper location (ECX).
		 mov ecx, edi

		 // Initialize the result to zero.
		 xor edi, edi

		 // Make sure the string pointer begins 4-bytes behind the start so
		 // it will conform with the following algorithm.
		 sub ecx, 4

		 // Begin converting the string to an integer.
		NEXT_BLOCK:
			// Point to the next block.
			add ecx, 4

			// Read a 4-byte block of the string.
			mov eax, [ecx]

		PROCESS_DIGIT:
			// Have we encountered the null-terminator?
			cmp al, 0
			jz EXIT

			// Is the character _not_ of the binary, octal or decimal systems?
			cmp al, 0x39
			jg HEXADECIMAL

			// Binary, octal or decimal.
			sub al, 0x30
			jmp DIGIT_CONVERTED

			HEXADECIMAL:
				// Are we dealing with a lower-case hex-digit?
				cmp al, 0x46
				jg LOWER_CASE_HEX

				// Upper-case hexadecimal.
				sub al, 0x37
				jmp DIGIT_CONVERTED

				LOWER_CASE_HEX:
					// Lower-case hexadecimal.
				sub al, 0x57

		DIGIT_CONVERTED:
			// Temporarily store the digit block in EBP.
			mov ebp, eax

			// Multiply the digit by it's positional value, to get the ultimate value
			// of the digit.
			movzx eax, al
			mul ebx

			// Add the value of the digit to the result.
			add edi, eax 

			// Calculate the positional-value of the next digit to the right.
			mov eax, ebx
			div esi
			mov ebx, eax

			// Return the digit block to EAX.
			mov eax, ebp

			// Mask out the digit just processed, and load the next digit into AL.
			mov al, 0xFF
			ror eax, 8

			// Have we completed the whole block?
			cmp eax, 0xFFFFFFFF
			jz NEXT_BLOCK

			// Process the next digit.
			jmp PROCESS_DIGIT
			
		EXIT:
			// Return the result of the conversion.
			mov eax, edi

			// Return original registers, and operation flags.
			pop ebp
			pop edi
			pop esi
			pop edx
			pop ecx
			pop ebx
			popfd
	}
}

Last edited by MattBro; 01-02-2007 at 06:34 AM.
MattBro is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Reddit!
Reply With Quote
Important Information
Join the #1 Tech Support Forum Today - It's Totally Free!

TechSupportForum.com is a leading support website for your computer needs. We offer free, friendly and personalized computer support. Why pay to have your computer fixed when you can do it for free.

Join TechSupportforum.com Today - Click Here

Reply


Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off




All times are GMT -7. The time now is 09:20 AM.



Copyright 2001 - 2009, Tech Support Forum
Home Tips Plus | Outdoor Basecamp | Automotive Support Forum

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85