hi,

Im a complete newbie at assembler, so please dont bash  :(

My problem is this, im trying to construct a simple inline routine in c++ using this code:


#include "stdafx.h"
#include <stdio.h>

void Test1(char* pData);

char format[] = "%d\n";

int _tmain(int argc, _TCHAR* argv[])
{
char* pData = "123";
Test1(pData);

return 0;
}

void Test1(char* pData)
{
_asm
{
xor eax, eax                                      ; zero eax
mov al, byte ptr pData[0]       ; <--- Problem is here!!

push eax ; Push last arg
mov  eax , offset format ; Copy format pointer to eax
push eax ; Push format arg onto stack
call printf ; Print out the value of data[0]

pop ebx ; Cleanup stack
pop ebx ; ...
}

int x;
std::cin >> x;
}


Im simply trying to copy the first byte of the char array 'pData[0]' into the al register, but the value 28 is always printed, am i doing something wrong here?

I read that al is the lower 8 bits of of eax, is this correct? or am i maybe doing this wrong?
Posted on 2005-03-17 10:26:34 by SexyBeast
You're loading 'al' with POINTER's least significant byte, not the value's.

use this:

_asm
{
? ? ? ? xor eax, eax? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; zero eax
mov edx, pData? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; laod edx with the pointer
mov al, ? ? ? ; <--- load al with first byte at pointer (change the 0 to a different value if you need next bytes. you can also use:? mov al, ? ?(with appropriately prepared ECX) . . .an so on...

push eax ; Push last arg
mov? eax , offset format ; Copy format pointer to eax
push eax ; Push format arg onto stack
call printf ; Print out the value of data[0]

pop ebx ; Cleanup stack
pop ebx ; ...
}


of course this code can be greatly optimised, but that's a different story... :P
Posted on 2005-03-17 10:57:06 by ti_mo_n
Thank you so much, this was driving me crazy :P

Just a quick question, isn't there a way to load//access an array like this without first putting the pointer to it in a register i.e like myArray[0]
Posted on 2005-03-17 12:30:57 by SexyBeast
contains the address to your data. If you read pData[0] you are reading the address of your data and not your actual data.
Posted on 2005-03-17 12:47:50 by roticv

contains the address to your data. If you read pData[0] you are reading the address of your data and not your actual data.


Ok, i guess im so used to c/c++, i expected to beable to do the equivilent of:


BYTE val = *(BYTE*)pData


In one line. Im slowly learning the hard way :)
Posted on 2005-03-17 12:59:04 by SexyBeast
In x86 assembly, you cannot have memory to memory transfer instructions, the only exceptions being movsb/w/d which do the equivalent of loading data into a temporary register and then saving it to the destination address.

Since his example shows the usage of char* pData, the memory pointer to pData would be a DWORD contaning the pointer the actual address that holds the said data so he would need to use LEA like so...
	
lea edx,DWORD
movzx eax,BYTE


I'll quickly explain both instructions...
LEA (Load Effective Address) loads data from memory using pData's 32-bit value as a memory pointer.
MOVZX (Move with Zero Extend) loads data from memory using a specified size, it only loads the specified amount from memory and zeros-out the rest of the register. It is equivalent to using XOR EAX,EAX with MOV AL,BYTE.

Your new code would look like this...

_asm{
lea edx,DWORD ;load the pointer
movzx eax,BYTE ;load the data
push eax ;push the data
push format ;Push the offset of format onto the stack
call printf ;Call PrintF
add esp,0x02 ;Reset the stack pointers used
}


Someone will need to translate this to MASM since I am a strict NASM type person ;)
Posted on 2005-03-22 01:40:43 by SpooK