【问题标题】:XMM register storingXMM寄存器存储
【发布时间】:2012-07-11 19:48:11
【问题描述】:

我正在尝试将 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 //看起来不对:(

//然后程序卡住了

基本上,我是否正确地执行了这个过程?你认为它为什么会卡住?

感谢您的时间和精力。

【问题讨论】:

    标签: gcc assembly x86 inline-assembly


    【解决方案1】:

    如果您想要一个 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;

    【讨论】:

    • 我明白你的意思,但不幸的是它仍然冻结与 -1 相同的输出:(
    • 我很抱歉,我是实习生,正在尝试学习这些东西,但我还没有学会单步执行工具,所以这就是我问的原因。仅供参考
    • 这里还有一个问题:__asm__("movdqa %%xmm0, $0\n" : "=m"(end_address));。该指令将用XMM0 中的内容覆盖变量end_address 的内容。你想要那个吗?像"=m"(*end_address) 这样的东西怎么样?
    • 还有一个问题是$0。应该是%0__asm__("movdqa %%xmm0, %0\n" : "=m"(*end_address)); 应该可以工作。你真的需要学习 te gcc 内联汇编语法。
    • 那是我真正感到困惑的事情......在 asm 中只有它是 'movdqa %%xmm0, 0x23434' 所以我认为你会继续并将 end_address 作为包含数字的变量传递这样 end_address = 0x234 而不是指针 *end_address = 0x234。此外,我已将 end_address 声明为变量而不是指针。那么这会奏效吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    • 2017-10-29
    • 1970-01-01
    • 2017-03-30
    • 2012-04-14
    • 1970-01-01
    • 2012-07-22
    相关资源
    最近更新 更多