assembly - 如何在 x86(32 位)程序集中将无符号整数转换为 float ?

标签 assembly x86 sse

我需要同时转换 32 位和 64 位 无符号整数 转换为 xmm 寄存器中的浮点值。有 x86 指令可以将有符号整数转换为单精度和 double 浮点值,但没有用于无符号整数。

奖励:如何将 xmm 寄存器中的浮点值转换为 32 位和 64 位无符号整数?

最佳答案

这是 GCC 生成的内容。我将它们包装在函数中,但您可以轻松删除堆栈处理。不是所有的都使用SSE来做实际工作(ulonglong转换没有),如果你找到相应的说明,请告诉我。 Clang 生成的几乎相同。

% cat tofloats.c 
double ulonglong2double(unsigned long long a) {
    return a;
}
float ulonglong2float(unsigned long long a) {
    return a;
}
double uint2double(unsigned int a) {
    return a;
}
float uint2float(unsigned int a) {
    return a;
}
% gcc -msse4.2 -g -Os -c tofloats.c && objdump -d tofloats.o
00000000 <ulonglong2double>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 10                sub    $0x10,%esp
   6:   8b 55 0c                mov    0xc(%ebp),%edx
   9:   8b 45 08                mov    0x8(%ebp),%eax
   c:   89 55 f4                mov    %edx,-0xc(%ebp)
   f:   85 d2                   test   %edx,%edx
  11:   89 45 f0                mov    %eax,-0x10(%ebp)
  14:   df 6d f0                fildll -0x10(%ebp)
  17:   79 06                   jns    1f <ulonglong2double+0x1f>
  19:   d8 05 00 00 00 00       fadds  0x0
  1f:   dd 5d f8                fstpl  -0x8(%ebp)
  22:   dd 45 f8                fldl   -0x8(%ebp)
  25:   c9                      leave  
  26:   c3                      ret    

00000027 <ulonglong2float>:
  27:   55                      push   %ebp
  28:   89 e5                   mov    %esp,%ebp
  2a:   83 ec 10                sub    $0x10,%esp
  2d:   8b 55 0c                mov    0xc(%ebp),%edx
  30:   8b 45 08                mov    0x8(%ebp),%eax
  33:   89 55 f4                mov    %edx,-0xc(%ebp)
  36:   85 d2                   test   %edx,%edx
  38:   89 45 f0                mov    %eax,-0x10(%ebp)
  3b:   df 6d f0                fildll -0x10(%ebp)
  3e:   79 06                   jns    46 <ulonglong2float+0x1f>
  40:   d8 05 00 00 00 00       fadds  0x0
  46:   d9 5d fc                fstps  -0x4(%ebp)
  49:   d9 45 fc                flds   -0x4(%ebp)
  4c:   c9                      leave  
  4d:   c3                      ret    

0000004e <uint2double>:
  4e:   55                      push   %ebp
  4f:   89 e5                   mov    %esp,%ebp
  51:   83 ec 08                sub    $0x8,%esp
  54:   66 0f 6e 45 08          movd   0x8(%ebp),%xmm0
  59:   66 0f d6 45 f8          movq   %xmm0,-0x8(%ebp)
  5e:   df 6d f8                fildll -0x8(%ebp)
  61:   c9                      leave  
  62:   c3                      ret    

00000063 <uint2float>:
  63:   55                      push   %ebp
  64:   89 e5                   mov    %esp,%ebp
  66:   83 ec 08                sub    $0x8,%esp
  69:   66 0f 6e 45 08          movd   0x8(%ebp),%xmm0
  6e:   66 0f d6 45 f8          movq   %xmm0,-0x8(%ebp)
  73:   df 6d f8                fildll -0x8(%ebp)
  76:   c9                      leave  
  77:   c3                      ret
以下是奖励积分(转换为整数):
% cat toints.c                                      
unsigned long long float2ulonglong(float a) {
    return a;
}
unsigned long long double2ulonglong(double a) {
    return a;
}
unsigned int float2uint(float a) {
    return a;
}
unsigned int double2uint(double a) {
    return a;
}
% gcc -msse4.2 -g -Os -c toints.c && objdump -d toints.o  
00000000 <float2ulonglong>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   53                      push   %ebx
   4:   83 ec 0c                sub    $0xc,%esp
   7:   d9 45 08                flds   0x8(%ebp)
   a:   d9 05 00 00 00 00       flds   0x0
  10:   d9 c9                   fxch   %st(1)
  12:   db e9                   fucomi %st(1),%st
  14:   73 0d                   jae    23 <float2ulonglong+0x23>
  16:   dd d9                   fstp   %st(1)
  18:   dd 4d f0                fisttpll -0x10(%ebp)
  1b:   8b 45 f0                mov    -0x10(%ebp),%eax
  1e:   8b 55 f4                mov    -0xc(%ebp),%edx
  21:   eb 13                   jmp    36 <float2ulonglong+0x36>
  23:   de e1                   fsubp  %st,%st(1)
  25:   dd 4d f0                fisttpll -0x10(%ebp)
  28:   8b 55 f4                mov    -0xc(%ebp),%edx
  2b:   8b 45 f0                mov    -0x10(%ebp),%eax
  2e:   8d 8a 00 00 00 80       lea    -0x80000000(%edx),%ecx
  34:   89 ca                   mov    %ecx,%edx
  36:   83 c4 0c                add    $0xc,%esp
  39:   5b                      pop    %ebx
  3a:   5d                      pop    %ebp
  3b:   c3                      ret    

0000003c <double2ulonglong>:
  3c:   55                      push   %ebp
  3d:   89 e5                   mov    %esp,%ebp
  3f:   53                      push   %ebx
  40:   83 ec 0c                sub    $0xc,%esp
  43:   dd 45 08                fldl   0x8(%ebp)
  46:   d9 05 00 00 00 00       flds   0x0
  4c:   d9 c9                   fxch   %st(1)
  4e:   db e9                   fucomi %st(1),%st
  50:   73 0d                   jae    5f <double2ulonglong+0x23>
  52:   dd d9                   fstp   %st(1)
  54:   dd 4d f0                fisttpll -0x10(%ebp)
  57:   8b 45 f0                mov    -0x10(%ebp),%eax
  5a:   8b 55 f4                mov    -0xc(%ebp),%edx
  5d:   eb 13                   jmp    72 <double2ulonglong+0x36>
  5f:   de e1                   fsubp  %st,%st(1)
  61:   dd 4d f0                fisttpll -0x10(%ebp)
  64:   8b 55 f4                mov    -0xc(%ebp),%edx
  67:   8b 45 f0                mov    -0x10(%ebp),%eax
  6a:   8d 8a 00 00 00 80       lea    -0x80000000(%edx),%ecx
  70:   89 ca                   mov    %ecx,%edx
  72:   83 c4 0c                add    $0xc,%esp
  75:   5b                      pop    %ebx
  76:   5d                      pop    %ebp
  77:   c3                      ret    

00000078 <float2uint>:
  78:   55                      push   %ebp
  79:   89 e5                   mov    %esp,%ebp
  7b:   83 ec 08                sub    $0x8,%esp
  7e:   d9 45 08                flds   0x8(%ebp)
  81:   dd 4d f8                fisttpll -0x8(%ebp)
  84:   8b 45 f8                mov    -0x8(%ebp),%eax
  87:   c9                      leave  
  88:   c3                      ret    

00000089 <double2uint>:
  89:   55                      push   %ebp
  8a:   89 e5                   mov    %esp,%ebp
  8c:   83 ec 08                sub    $0x8,%esp
  8f:   dd 45 08                fldl   0x8(%ebp)
  92:   dd 4d f8                fisttpll -0x8(%ebp)
  95:   8b 45 f8                mov    -0x8(%ebp),%eax
  98:   c9                      leave  
  99:   c3                      ret    
有函数从堆栈中获取输入并通过堆栈返回它。如果在函数结束时需要 XMM 寄存器中的结果,则可以使用 movd/movq 将它们从堆栈中取出到 XMM。如果函数返回 double 值,则结果为 -0x8(%ebp)。如果它是一个浮点数,结果是 -0x4(%ebp)。 Ulonglongs 的长度是 doubles 的长度,ints 的长度是 floats 的长度。
fisttpll:存储带有截断的整数

FISTTP converts the value in ST into a signed integer using truncation (chop) as rounding mode, transfers the result to the destination, and pop ST. FISTTP accepts word, short integer, and long integer destinations.


fucomi:比较浮点值并设置 EFLAGS

Performs an unordered comparison of the contents of registers ST(0) and ST(i) and sets the status flags ZF, PF, and CF in the EFLAGS register according to the results (see the table below). The sign of zero is ignored for comparisons, so that –0.0 is equal to +0.0.

关于assembly - 如何在 x86(32 位)程序集中将无符号整数转换为 float ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11406654/

相关文章:

linux - x86 NASM Linux 程序集中的 ATOI 问题

gcc - 汇编代码 `movl %1, %%ebx`是什么意思?

linux - IA 32 读取命令行参数

c++ - g++ 4.6.1 编译器错误 : Error: unknown pseudo-op: `.cfi_personality'

linux - 为什么此汇编代码没有再次读取相同的字节,而是返回文件结尾?

c++ - SSE 和 AVX 内在函数混合

c++ - 告诉 GCC "I want to use SSE4.1, but ONLY in the places I want!"

c++ - 从 avx/sse 掩码到 avx512 掩码的 "correct"方法是什么?

assembly - x86 jmp 注册

c - 将四字移动到 %RDI 的操作码