结论
在使用__int128时,如果__int128类型的内存起始地址不是按16字节对齐的话,有些汇编指令会抛出SIGSEGV使程序crash。
malloc在64位系统中申请的内存地址,是按16字节对齐的,但一般使用时经常会申请一块内存自己切割使用,往往会忽略一些类型的对齐。
案例
目前知道的两个指令是msse指令集的movaps和vmovaps,都是用来给int128赋值的,例如下面两种场景:
- (访问rax+0x30地址即 0x328dba8 + 0x30 = 0x328dbd8,对齐8字节,但没对齐16字节)
- (访问rax+0x30地址即 0x2d20b48 + 0x20 = 0x2d20b68,对齐8字节,但没对齐16字节)
复现
#include <stdio.h>
// gcc -g -O2 -Wall -msse4.2 -o test test.c
// core
typedef unsigned __int128 uint128;
// no core
// typedef unsigned __int128 uint128 __attribute__((aligned(8)));
static char mem[100];
typedef struct MySt
{
int a;
uint128 i;
int b;
} MySt;
int main(void)
{
MySt *st = (MySt *)(mem + 1);
printf("st = %p\n", st);
printf("st->i = %p\n", &st->i);
__int128 tmp = 123123;
st->a = 0;
st->i = tmp * 123;
st->b = 0;
st = st;
return st->i + 1 == 123;
}
gcc -g -O2 -Wall -msse4.2 -o test test.c
可复现(不同的机器、编译器版本有不同的效果,可以看下编出来的二进制有无movaps指令,如果都是mov肯定没问题)。