I'm having to convert an inline assembly block from MSVC to MinGW (it cannot be written in C++, as it passes a runtime-determined number of arguments to function calls) - I've got it all converted, except that there is an error that I can't resolve. I have absolutely no assembly experience, and apparently I'm not good at Googling because I can't find anything relevant to my error.
I have this assembly line:
fstp Result;
Where Result is an int declared before the assembly block. The error I am getting is:
AppData\Local\Temp\cc7Qc9sw.s: Assembler messages:
AppData\Local\Temp\cc7Qc9sw.s:4638: Error: ambiguous operand size for `fstp'
All I know is that the variable Result is supposed to take the value of a float, as if by a reinterpret_cast.
Professional Asembly Language by Richard Blum wrote:
The FSTP instruction also copies the ST0 FPU register value, but then pops it from the FPU register
stack. This shifts all of the FPU stack values up one place in the stack.
Don’t forget to add the data size character to the end of the FST and FSTP mnemonics to specify the
proper size of the resulting data value. In this example, the FSTPS instruction is used to create a singleprecision
floating-point value stored in 4 bytes (32 bits) of memory from the value in the ST0 FPU stack
position:
Sorry try: FSTP DWORD PTR[Result];
or FSTP DWORD [Result];
Although it is probably the former that would work.
I am assuming result holds a pointer to a memory address, if not then you are trying to copy a 32 bit float to a 32 bit int and that is not going to end well.
int * Parameters;
int ParameterCount;
void * Function = ::SDK->ExpressionFunctions[ID];
//...code to load parameters...
void * Extension = rdPtr->pExtension;
int Result;
int ExpressionType = ::SDK->ExpressionTypes[ID];
__asm
{
pushad
mov ecx, ParameterCount
cmp ecx, 0
je CallNow
mov edx, Parameters
mov ebx, ecx
shl ebx, 2
add edx, ebx
sub edx, 4
PushLoop:
push [edx]
sub edx, 4
dec ecx
cmp ecx, 0
jne PushLoop
CallNow:
mov ecx, Extension
call Function
mov ecx, ExpressionType;
cmp ecx, 1
jne NotFloat
fstp Result
jmp End
NotFloat:
mov Result, eax
End:
popad
}
return Result;
To convert it to MinGW's inline assembly format, all I am doing is changing __asm to __asm__, changing the curly braces to parens, and placing all the instructions in quotes with semicolons after them. The code works correctly as-is in MSVC, but the fstp Result line will not compile under MinGW.
fst and fstp are the same, except that fstp pops ST0 from the stack.
The answer and comments I linked had the same error message you are getting which doesn't occur in regular gcc or MSVC, but does in mingw. The OP got his code to work with mingw by specifying size in the instruction (fstps for you) and using constraints (neither of which you appear to be doing.)
First off, what does the following do: void * Function = ::SDK->ExpressionFunctions[ID];void * Extension = rdPtr->pExtension;int ExpressionType = ::SDK->ExpressionTypes[ID];
Secondly, the instruction fstp does the following AFAIK: http://docs.oracle.com/cd/E19455-01/806-3773/instructionset-133/index.html
So it stores the floating point value at the top of the FPU stack somewhere, and then pops it off the stack, right?
Now in your example Result is declared as an int. Should it not be a float pointer or an actual float?
I am sorry if I am terribly misinterpreting what is happening, but I am just trying to help.
@Script Coder: Function is the address of the member function to be called, Extension is the this pointer. ExpressionType is either 0 (int), 1 (float), or 2 (char *). In the example it has to be an int because that is what is getting returned from the DLL back to the software, which interprets the return value as the correct type.
If you want to access elements outside you have to specify them. As far as i know, unless there is a compiler setting that changes that. GCC at least uses AT&T syntax, you are using Intels unless you specify otherwise.