Problem about put Assembly in C++

Started by
5 comments, last by Argoran 17 years, 2 months ago
I am not sure if this is a right question for here, so if it's not for here, I'm sorry. I'm trying to put some Assembly in my program. But I didn't get a successful start. I wrote some code to simulate the 'd' order in debug, hoping that it will show me the content of the memmory I selected. It passed the compile phase with no error, but got run time error. I debuged and got an error:access violation. at "mov ds ax" and an error:illegal reference to 16-bit data in 'second operand'. at "mov al,ds:[bx]" Here is my code:

#include <string>
#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

short ConvertToShort(string);

const int LOOPNUM = 128;  
   
int main()
{
	string x1,x2,x3;  //x1 for input, x2 for ds,x3 for offset
	cout<<"-";
	cin>>x1;
	
	bool bX2 = false; 
	for(int index = 0; index < x1.length(); index++)
	{
		if(x1[index]==':')
		{
			bX2 = true;
		}
		else
		{
		    if(!bX2)
			{
                x2 += x1[index];
			}
		    else
			{
			    x3 += x1[index]; 
			}
		}
	}

	short dp = ConvertToShort(x2),
		  ap = ConvertToShort(x3);
	
	unsigned char output = 0;

	for(short i = 0; i < LOOPNUM; i++)
	{
	_asm
	{
        mov ax,dp
		mov ds,ax
		sub bx,bx
		mov bx,ap
		add bx,i
		sub ax,ax
		mov al,ds:[bx]
		mov output,al
	}

	cout<<hex<<output<<"  ";
	
	if((i+1)%8 == 0)
		cout<<endl;
	}

	return(0);
}

short ConvertToShort(string str)
{
	short temp = 0
		 ,ret  = 0;
	const char* tstr = str.c_str();
	for(int index =0 ; index < str.length(); index++)
	{
		switch(tstr[index])
		{
		case '0':
			temp = 0;break;
		case '1':
			temp = 1;break;
		case '2':
			temp = 2;break;
		case '3':
			temp = 3;break;
		case '4':
			temp = 4;break;
		case '5':
			temp = 5;break;
		case '6':
			temp = 6;break;
		case '7':
			temp = 7;break;
		case '8':
			temp = 8;break;
		case '9':
			temp = 9;break;
		case 'A':
			temp = 10;break;
		case 'B':
			temp = 11;break;
		case 'C':
			temp = 12;break;
		case 'D':
			temp = 13;break;
		case 'E':
			temp = 14;break;
		case 'F':
			temp = 15;break;
		case 'a':
			temp = 10;break;
		case 'b':
			temp = 11;break;
		case 'c':
			temp = 12;break;
		case 'd':
			temp = 13;break;
		case 'e':
			temp = 14;break;
		case 'f':
			temp = 15;break;
		}
		ret += temp*pow(16,str.length()-1-index);
	}

	return(ret);
}



I use VC6.0, XP PRO SP2 and AMD athlon 902M.
Advertisement
get a 16bit DOS realmode compiler and try again, or use your OS API.
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
Does this work:
mov al,byte ptr ds:[bx]


BTW in protected mode (like in WinXP) you should never load segment descriptors (i.e. "mov ds, ax" is forbidden) nor you have the need to. Segmentation is virtually disabled by making the segments 4GB in size. Addressing memory is performed by using 32bit registers like eax or ebx, for instance "mov al, byte ptr [ebx]" loads an 8bit value from address ebx into al.

Edited:
You can't do this in 32-bit protected mode. If you could, all hell would break loose. Are you sure this is being compiled executed as kernel code? If not, you're not going to get very far.
_asm{        mov ax,dp	mov ds,ax	// DS is a segment register and shouldn't be written to in protected mode	sub bx,bx	// The standard way to clear a register is XOR BX, BX	mov bx,ap	// There is no need to clear BX if you're about to write to it	add bx,i	sub ax,ax	// As 'sub bx, bx'	mov al,ds:[bx]	// You don't need to qualify addresses in the data segment	mov output,al}
Also, I find it curious that you're using 16 bit registers when everything suggests that you should be using 32. Are you taking this code from an old source?

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Thank you for your help!

I'm a new learner of Assembly and the book I read all write code like that. I even don't know what ebx is. Is that a 32-bit register? Then what's the difference between ebx and bx? Does something like al or bh still exist?
Any article I can read about this?

I want to write something like FPE to lock hero's HP in some games, so if I can't qualify the data segment, how to access memmory belongs to the game?
Quote:Original posted by Argoran
I'm a new learner of Assembly and the book I read all write code like that. I even don't know what ebx is. Is that a 32-bit register? Then what's the difference between ebx and bx? Does something like al or bh still exist?
Any article I can read about this?

I want to write something like FPE to lock hero's HP in some games, so if I can't qualify the data segment, how to access memmory belongs to the game?

I strongly recommend you get a new book [rolleyes].
The maximum physical memory allowed in a x86 computer is 4GB, which, by no coincidence, is the number of bytes addressable in a 32 bit register. For this reason, there is no real need to qualify which segment you want to access: the value of the pointer should be enough to leave the segment implicit.

I'm not sure what FPE is, but as for how to access the game's memory, all you need to know is that it just works. You dereference a pointer, and the kernel will do all the work. In protected mode, the kernel is doing a lot of work to keep the processes separate, so that none can (easily) damage another. For this reason, addresses in protected mode applications are all relative, and are translated by the kernel behind the scenes into a physical address.
You don't need to know any of the implementation details to get by, but it's nice to know a few things, when debugging:

1. An address below 0x1000 is certainly invalid.
2. An address that looks like 0x0012xxxx belongs to the main thread's stack.
3. An address in the range 0x00400000-0x00600000 is most likely part of the excutable image, be that code (say, a function) or constant data.
4. Higher addresses up to 0x10000000 belong to one of your application's heaps.
5. An address above 0x10000000 generally belongs to a DLL.
6. Anything above 0x7FFFFFFF is probing into kernel territory and may not be accessed from usermode.

Obviously, there's a lot more to it, but if you do something you shouldn't, the exception handler will usually let you know about it.

Finally, EBX is indeed a 32-bit register. Any register beginning with E is 32-bit (it stands for extended).

I'm sure your book has told you about BX, which is a general-purpose word-sized register. It is made up of two bytes, BL and BH (low and high, respectively). Well since the days of 32-bit processors, it has been upgraded to EBX, a dword. EBX is made up of a the 'low word' BX and an unnamed high word.
While you can still legally and safely access BX, BH and BL, it's not commonly done, as acting on EBX is faster and less overflow-prone.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Thank you very much! Really helped a lot.

This topic is closed to new replies.

Advertisement