我目前正在从为GCC Linux编写的https://github.com/mono项目中将一些代码移植到MS Windows x64,我遇到了一些挑战。
目前我不确定从x64 AT& T内联ASM到x64 MASM的翻译是否正确。它编译得很好但我的测试用例失败,因为memcpy
在我的ASM函数执行后抛出异常/内存访问冲突。 我的翻译是否正确?
我真正面临的挑战之一是在Windows x64 MASM中无法访问rip
这一事实?我真的不知道如何翻译AT& T语法的剩余行(见下文)。但我给了它一个最好的尝试。 我是否正确处理了rip
访问权限的缺失?
如果我的工作正确,那么为什么memcpy
失败?
以下是相关的C ++:
void mono_context_get_current(MonoContext cnt); //declare the ASM func
//Pass the static struct pointer to the ASM function mono_context_get_current
//The purpose here is to clobber it
#ifdef _MSC_VER
#define MONO_CONTEXT_GET_CURRENT(ctx) do { \
mono_context_get_current(ctx); \
} while (0)
#endif
static MonoContext cur_thread_ctx = {0};
MONO_CONTEXT_GET_CURRENT (cur_thread_ctx);
memcpy (&info->ctx, &cur_thread_ctx, sizeof (MonoContext)); //memcpy throws Exception.
这是当前的ASM功能。
mono_context_get_current PROTO
.code
mono_context_get_current PROC
mov rax, rcx ;Assume that rcx contains the pointer being passed
mov [rax+00h], rax
mov [rax+08h], rbx
mov [rax+10h], rcx
mov [rax+18h], rdx ;purpose is to offset from my understanding of the GCC assembly
mov [rax+20h], rbp
mov [rax+28h], rsp
mov [rax+30h], rsi
mov [rax+38h], rdi
mov [rax+40h], r8
mov [rax+48h], r9
mov [rax+50h], r10
mov [rax+58h], r11
mov [rax+60h], r12
mov [rax+68h], r13
mov [rax+70h], r14
mov [rax+78h], r15
call $ + 5
mov rdx, [rax+80h]
pop rdx
mono_context_get_current ENDP
END
据我了解, rcx
注册表应包含结构指针,我应该使用rdx
到pop
。
正如我所提到的,对于非Win64平台,我有GCC ASM,它似乎可以在这些平台上运行。这就是代码的样子:
#define MONO_CONTEXT_GET_CURRENT(ctx) \
__asm__ __volatile__( \
"movq $0x0, 0x00(%0)\n" \
"movq %%rbx, 0x08(%0)\n" \
"movq %%rcx, 0x10(%0)\n" \
"movq %%rdx, 0x18(%0)\n" \
"movq %%rbp, 0x20(%0)\n" \
"movq %%rsp, 0x28(%0)\n" \
"movq %%rsi, 0x30(%0)\n" \
"movq %%rdi, 0x38(%0)\n" \
"movq %%r8, 0x40(%0)\n" \
"movq %%r9, 0x48(%0)\n" \
"movq %%r10, 0x50(%0)\n" \
"movq %%r11, 0x58(%0)\n" \
"movq %%r12, 0x60(%0)\n" \
"movq %%r13, 0x68(%0)\n" \
"movq %%r14, 0x70(%0)\n" \
"movq %%r15, 0x78(%0)\n" \
"leaq (%%rip), %%rdx\n" \
"movq %%rdx, 0x80(%0)\n" \
: \
: "a" (&(ctx)) \
: "rdx", "memory")
感谢您提供的任何帮助!我是第一个承认我的大会很生锈的人。
答案 0 :(得分:0)
你可以让gcc为你创建asm文件(gcc也可以生成MASM语法):
gcc -S -masm=intel myfile.c
答案 1 :(得分:0)
两个版本之间的比较似乎存在一些差异:
movq $0x0, 0x00(%0)
看起来rax
似乎没有被保存,而是将内存插槽清零。
leaq (%%rip), %%rdx
您应该能够将其转换为intel synatx:
lea rdx, [rip]
如果您使用的是64位相对寻址模式,则该命令有效。
此行从att:
错误地翻译call $ + 5
mov rdx, [rax+80h] ; looks reversed
pop rdx
以下是我翻译原始气体语法的方法:
mov qword ptr [rcx], 0
mov [rcx + 0x08], rbx
mov [rcx + 0x10], rax
mov [rcx + 0x18], rdx
mov [rcx + 0x20], rbp
mov [rcx + 0x28], rsp
mov [rcx + 0x30], rsi
mov [rcx + 0x38], rdi
mov [rcx + 0x40], r8
mov [rcx + 0x48], r9
mov [rcx + 0x50], r10
mov [rcx + 0x58], r11
mov [rcx + 0x60], r12
mov [rcx + 0x68], r13
mov [rcx + 0x70], r14
mov [rcx + 0x78], r15
lea rdx, [rip]
mov [rcx + 0x80], rdx
mov rdx, [rcx + 0x18] ; restore old rdx since it's on clobber list
请注意,为了节省额外的rcx
,我使用rax
切换了mov
。因此,rax
代替rcx
保存在气体语法中。您可能需要根据不变量修改此值。
如果它仍然崩溃,我建议用调试器逐步完成它。