Существует несколько способов встраивания констант в поток инструкций:
- используя непосредственные операнды
- путем загрузки с адресов, относящихся к ПК
Таким образом, хотя нет возможности выполнить немедленную загрузку в регистр XMM
, можно выполнить загрузку относительно ПК (в 64-битном режиме) из значения, хранящегося «рядом» с местом выполнения кода. Это создает что-то вроде:
.align 4
.val:
.long 0x12345678
.long 0x9abcdef0
.long 0xfedbca98
.long 0x76543210
func:
movdqa .val(%rip), %xmm0
При разборке:
0000000000000000 :
0: 78 56 34 12 f0 de bc 9a
8: 98 ca db fe 10 32 54 76
0000000000000010 :
10: 66 0f 6f 05 e8 ff ff movdqa -0x18(%rip),%xmm0 # 0
который имеет чрезвычайно компактный размер 23 байта.
Другие варианты - создать значение в стеке и снова загрузить его оттуда. В 32-битной системе x86, где у вас нет %rip
-относительного доступа к памяти, можно сделать это за 24 байта (при условии, что указатель стека выровнен при входе; в противном случае требуется невыровненная загрузка):
00000000 :
0: 68 78 56 34 12 push $0x12345678
5: 68 f0 de bc 9a push $0x9abcdef0
a: 68 98 ca db fe push $0xfedbca98
f: 68 10 32 54 76 push $0x76543210
14: 66 0f 6f 04 24 movdqa (%esp),%xmm0
В 64-битном режиме (выравнивание указателя стека при входе в функцию там гарантируется ABI) это займет 27 байт:
0000000000000000 :
0: 48 b8 f0 de bc 9a 78 56 34 12 movabs $0x123456789abcdef0,%rax
a: 50 push %rax
b: 48 b8 10 32 54 76 98 ba dc fe movabs $0xfedcba9876543210,%rax
15: 50 push %rax
16: 66 0f 6f 04 24 movdqa (%rsp),%xmm0
Если вы сравните любую из них с версией MOVLHPS
, вы заметите, что она самая длинная:
0000000000000000 :
0: 48 b8 f0 de bc 9a 78 56 34 12 movabs $0x123456789abcdef0,%rax
a: 66 48 0f 6e c0 movq %rax,%xmm0
f: 48 b8 10 32 54 76 98 ba dc fe movabs $0xfedcba9876543210,%rax
19: 66 48 0f 6e c8 movq %rax,%xmm1
1e: 0f 16 c1 movlhps %xmm1,%xmm0
на 33 байтах.
Другое преимущество загрузки непосредственно из памяти команд состоит в том, что movdqa
не зависит от чего-либо предыдущего. Скорее всего, первая версия, предоставленная @Paul R, является самой быстрой из возможных.
person
FrankH.
schedule
12.07.2011