gpt4 book ai didi

c - movsd 从内存到 c x86-64 jit 中的 xmm0

转载 作者:太空宇宙 更新时间:2023-11-04 07:46:13 25 4
gpt4 key购买 nike

我正在尝试编写一个小型 x86-64 JIT,但我在一些地方有点难以理解。

我正在尝试 JIT 一个简单的函数,该函数将 float 的值分配给 xmm0 寄存器,然后返回它,但我不确定应该如何对 movsd 调用的参数进行编码。

如有任何帮助,我们将不胜感激。

/* main.c */
#include <stdio.h>
#include <sys/mman.h>

#define xmm(n) (n)

typedef double(*fn)();

fn jit(){
char* memory = mmap(NULL,
4096,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0);
int i=0;
float myfloat = 3.1f;
memory[i++] = 0x48; /* REX.W */
memory[i++] = 0xf2; /*******************/
memory[i++] = 0x0f; /* MOVSD xmm0, m64 */
memory[i++] = 0x10; /*******************/

memory[i++] = 0x47 | xmm(0) << 3; /* Not 100% sure this is correct */

memory[i++] = 0; /* what goes here to load myfloat into xmm0? */

memory[i++] = 0xc3; /* RET */
return (fn) memory;
}

int main(){
fn f = jit();
printf("result: %f\n", (*f)());
return 0;
}

最佳答案

SSE 指令通常不支持立即数,除了一些使用单字节立即数来控制其操作的罕见指令。因此你需要:

  • myfloat 存储到附近的内存区域
  • 生成一个引用该区域的内存操作数

这两个步骤都很简单。对于第一步,我将简单地使用 memory 的开头,然后让代码立即开始。请注意,在这种情况下,您需要确保返回指向函数开头的指针,而不是 memory 的开头。其他解决方案也是可能的。只需确保 myfloat 存储在代码的 ±2 GiB 范围内。

要生成操作数,请重新访问 Intel 手册。您想要的寻址模式是一个 32 位 RIP 相关操作数。这是用 mod = 0,r/m = 5 生成的。位移是一个带符号的 32 位数字,它在指令末尾添加到 RIP 的值(这是 +4 的来源,因为必须考虑因素在位移的长度)。

因此我们有类似的东西:

memory[i++] = 0xf2; /*******************/
memory[i++] = 0x0f; /* MOVSD xmm0, m64 */
memory[i++] = 0x10; /*******************/
memory[i++] = 0005 | xmm(0) << 3; /* mod = 0, r/m = 5: [rip + disp32] */
*(int *)(memory + i) = memory + i + 4 - addr_of_myfloat;
i += 4;
memory[i++] = 0xc3; /* RET */

注意这里不需要REX前缀。

关于c - movsd 从内存到 c x86-64 jit 中的 xmm0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56778792/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com