Hi
I registered to ask a newbie question.
In a C/C++ project started by someone else and that I'm trying to improve, there's much inline assembler.

_STBus is an extern "C" pointer to BYTE (unsigned char*)
I want to move the word at _STBus to BX.
EBP is in bytes.

	
MOV EAX, EBP ; ST address
ADD EAX, _STBus ; PC address of ST bus
MOV BX,


Does work.


MOV BX,WORD PTR _STBus ; won't work


Doesn't work.
Isn't the second way supposed to do the same as the first? Is there no way to do that with a single MOV?
Posted on 2011-07-10 08:55:46 by dmc
What is the error you're getting?
At first sight, I think the most logical explanation why it doesn't work is because _STBus is a variable in memory, not a constant. In that case, the add is doing a reg+mem operation. Something that is not supported by the addressing modes.
This should work then:

mov eax, _STBus
mov bx, word ptr


Edit: After reading what you said more clearly:
"_STBus is an extern "C" pointer to BYTE (unsigned char*)"
Indeed, _STBus is a variable in memory (that's what a pointer is in C/C++, an address stored in memory), that's why it doesn't work. Addressing modes want a constant, or a second register.
Posted on 2011-07-10 09:12:57 by Scali
Most likely your issue is with segment registers.  by default will use DS and will use SS.
Obviously if the segment registers contain different values you will get different results.
During debug verify the segment register contents in both scenarios first and we'll go from there...
Posted on 2011-07-10 10:13:16 by p1ranha
Thanks, dudes.
The 2 lines code works.
I checked the segment registers, they have the same value in both cases.

In the code, there was such a line:
mov		bx,WORD PTR _STRam

Where _STRam is:
extern "C" BYTE STRam[16*1024*1024];


And for any reason, I want to use

extern "C" BYTE *STBus;


with somewhere in the C++ code:


STBus=STRam;


All lines like
mov		bx,WORD PTR _STRam

work, but not with _STBus. I get no error message but the program hangs.
So, is a C BYTE array treated another way than a BYTE pointer?
Posted on 2011-07-10 15:27:57 by dmc

So, is a C BYTE array treated another way than a BYTE pointer?


Yes, if you define an array directly, like BYTE array[1024];, then it is allocated statically.
In the global scope, it is placed in the .data? section of the executable. In a function scope, it is placed on the stack.
In this case, 'array' acts as a constant containing the address of the first element.
A pointer works differently.
If you do BYTE* pArray = array;, then it will assign the value of array to the variable pArray (which is stored in memory, just like any other variable, eg: int var;).

As you probably know, you cannot use delete on such a BYTE array. So it works quite differently from something like: BYTE* pArray = new BYTE[1024];
In this case, the array is dynamically allocated on the heap.
Posted on 2011-07-10 15:53:16 by Scali
OK, thanks.
I think I begin to understand. _STRam is the real array, _STBus is a pointer held somewhere else in RAM. By treating both the same way, I was trying to index from the place _STBus was, which was garbage &(&_STBus + EBP) instead of &(_STBus+EBP), while &(&_ST_Ram + EBP) was OK. Because in C, STRam == &STRam[0], I thought _STBus was equivalent to _STRam.
My intention is to transform the static allocation by a dynamic one, so I'll need to change the code. At least you saved me 1 line!
Posted on 2011-07-11 01:55:19 by dmc
Most likely your issue is with segment registers.  by default will use DS and will use SS.
Not a problem on Windows or Linux (and probably any modern OS) since they use flat addressing modes (different selectors, but descriptors all set up for addressing the full memory range, memory protection handled by paging).

Also, a thing to keep in mind: obey your compiler's calling convention, in this case specifically register preservation. Normal calling conventions on x86 require you to leave EBX,EBP,ESP (and the direction flag) unchanged on function exit - so if you modify any of those, be sure to restore them. EAX,ECX,EDX,ESI,EDI can be freely trashed (though of course EAX is return value).
Posted on 2011-07-13 17:40:27 by f0dder
Strange, from what I understand, the guy used BX as a parameter for a function call. They are typically "naked" C function fully inline assembly (__asm).
NAKED void Intercept_DiskControl_WriteWord(void)
{
__asm {
MOV EAX, 0xff8604
ADD EAX, STBus
MOV bx,
SWAP_ENDIAN_WORD_BX
call FDC_WriteDiscController
ret
}
}
Posted on 2011-07-14 14:35:04 by dmc
Ugh - looks like something that should have been written as external assembly modules instead... or, better, used C routines for it instead... for the code snippets you've shown, there's no advantage whatsoever of writing the routines in assembly :)
Posted on 2011-07-14 15:15:35 by f0dder