XMM寄存器存储

时间:2012-07-11 19:48:12

标签: gcc assembly x86 inline-assembly

我正在尝试将XMM寄存器存储到某个位置,例如地址行4534342。

示例:

我做了什么?

我知道xmm寄存器包含128位值。所以,我的程序已经生成了分配的16字节内存。另外,由于寄存器是对齐的数据,我已经分配了31个字节,然后在其中找到了一个对齐的地址。这应该可以防止任何异常被抛出。

我想在视觉上做些什么?

Mem Adr | Contents (binary)
4534342 | 0000 0000 0000 0000  ; I want to pass in address 4534342 and the
4534346 | 0000 0000 0000 0000  ; the program inline-assembly will store it 
4534348 | 0000 0000 0000 0000  ; its contents straight down to address 45-
4534350 | 0000 0000 0000 0000  ; 34350
4534352 | 0000 0000 0000 0000
4534354 | 0000 0000 0000 0000
4534356 | 0000 0000 0000 0000
4534358 | 0000 0000 0000 0000

设置

cyg_uint8 *start_value;      //pointer to the first value of the allocated block                    
cyg_uint32 end_address;      //aligned address location value
cyg_uint32 *aligned_value;   //pointer to the value at the end_address
start_value = xmm_container; //get the pointer to the allocated block
end_address = (((unsigned int) start_value) + 0x0000001f) & 0xFFFFFFF8; //find aligned memory
aligned_value =  ((cyg_uint32*)end_address);  //create a pointer to get the first value of the block

在汇编调用之前调试语句以确保函数

printf("aligned_value: %d\n", (cyg_uint32) aligned_value); printf("*aligned_value: %d\n", *aligned_value);

集会电话

__asm__("movdqa %%xmm0, %0\n" : "=m"(*aligned_value)); //assembly call

在程序集调用后调试语句以确保函数

printf("aligned_value: %d\n", (cyg_uint32) aligned_value);
printf("*aligned_value: %d\n", *aligned_value);

printf的输出[FAILURE]

  

aligned_value:1661836 //看起来不错!

     

* aligned_value:0 //看起来不错!

     

aligned_value:-1 //看起来不对:(

     

//然后程序卡住了

基本上,我正确地完成了这个过程吗?为什么你认为它会被卡住?

感谢您的时间和精力。

1 个答案:

答案 0 :(得分:4)

如果你想要一个16字节的对齐地址,我不认为你的对齐逻辑是正确的。

做数学,很容易!:

(0 + 0x1f)& 0xFFFFFFF8 = 0x18; 0x18-0 = 0x18未使用的字节,0x1F-0x18 =剩余7个字节
(1 + 0x1f)& 0xFFFFFFF8 = 0x20; 0x20-1 = 0x1F未使用的字节,0x1F-0x1F = 0字节左。
...
(8 + 0x1f)& 0xFFFFFFF8 = 0x20; 0x20-8 = 0x18未使用的字节,0x1F-0x18 =剩余7个字节
(9 + 0x1f)& 0xFFFFFFF8 = 0x28; 0x28-9 = 0x1F未使用的字节,0x1F-0x1F = 0字节左。
...
(0xF + 0x1f)& 0xFFFFFFF8 = 0x28; 0x28-0xF = 0x19未使用的字节,0x1F-0x19 =剩余6个字节
(0x10 + 0x1f)& 0xFFFFFFF8 = 0x28; 0x28-0x10 = 0x18未使用的字节,0x1F-0x18 =剩余7个字节
(0x11 + 0x1f)& 0xFFFFFFF8 = 0x30; 0x30-0x11 = 0x1F未使用的字节,0x1F-0x1F = 0字节左。
...
(0x18 + 0x1f)& 0xFFFFFFF8 = 0x30; 0x30-0x18 = 0x18未使用的字节,0x1F-0x18 =剩余7个字节
(0x19 + 0x1f)& 0xFFFFFFF8 = 0x38; 0x38-0x19 = 0x1F未使用的字节,0x1F-0x1F =左0字节
...
(0x1F + 0x1f)& 0xFFFFFFF8 = 0x38; 0x38-0x1F = 0x19未使用的字节,0x1F-0x19 =剩余6个字节

首先,要获得4个最低有效位中的全零,则掩码应为0xFFFFFFF0。

接下来,如果以这种方式计算对齐的地址,则会溢出31字节的缓冲区。你的数学会留下0到7个字节的空间,这不足以存储16个字节。

对于正确的16字节对齐,您应该写下:

end_address = (((unsigned int)start_value) + 0xF) & 0xFFFFFFF0;