Let me start by saying that I don't know much about Assembly, but this is something that I'm wondering about.
Let's say that I have a code in C++ such as the following:
float f = 34.2;
int i;
i = f;
Now obviously what will happen when this code gets executed is that the value of f
(34.2) will be converted to an integer value (34) and assigned to i
.
My question is how does this conversion happens, I mean does it happen at runtime, so at runtime there is a code embedded into the executable that goes something like this: f
is being assigned to i
, now I know that f
is a float and i
is an integer, so what I should do is convert the bits in the f
variable to an integer representation and then assign it to i
;
Or what happens is that at compile time the i = f
will directly be replaced by code that will convert a float to an integer?
Your code is
float f = 34.2;
int i;
i = f;
Just debug and have a look at the Dis-assembly Window. In a debug build (so constant-propagation doesn't happen, and the variables aren't optimized away entirely):
float f = 34.2;
01175498 movss xmm0,dword ptr ds:[117DF70h]
011754A0 movss dword ptr [f],xmm0
int i;
i = f;
011754A5 cvttss2si eax,dword ptr [f]
011754AA mov dword ptr [i],eax
You can see the instruction cvttss2si
(Convert with Truncation Scalar Single-Precision Floating-Point Value to Integer) is being executed.
This is what Mats Petersson said in his comment. This instruction will convert the float to its integer representation, with rounding towards 0 regardless of the current rounding mode.
The input operand is 32 bits wide, and is interpreted as IEEE single-precision because x86 uses that format for float
.
(C++ compilers targeting x86 without SSE1/SSE2 had to change the x87 rounding mode to truncation and then back to the previous value; that's why SSE1 and SSE2 included convert-with-truncation instructions but not other rounding-mode overrides, until SSE4.1 roundss
/roundsd
to implement floor/ceil/trunc/nearbyint with a floating-point result. C++ requires FP->integer conversions to truncate towards zero, separately from the default rounding mode when producing an FP result.)
Most other modern ISAs have a single instruction FP->int conversion with truncation instruction, although non-CISC ones can only operate between registers and would need separate load and store in a debug build.