Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C预处理器和"_asm“发射”;指示_C_Visual C++_Assembly_C Preprocessor_Inline Assembly - Fatal编程技术网

C预处理器和"_asm“发射”;指示

C预处理器和"_asm“发射”;指示,c,visual-c++,assembly,c-preprocessor,inline-assembly,C,Visual C++,Assembly,C Preprocessor,Inline Assembly,我试图在Visual Studio 2015中实现布尔运算和\u asm\u emit,想要在x86程序中插入一些x64操作码,我必须执行很多mov到内存的命令,所以我尝试制作某种宏,它采用地址并以小尾端形式发出,因此: #define EmitDword(x)\ {\ _asm _emit (x & 0x000000FF) \ _asm _emit ((x >> 8) & 0x000000FF) \ _asm _emit ((x >&g

我试图在Visual Studio 2015中实现布尔运算和
\u asm\u emit
,想要在x86程序中插入一些x64操作码,我必须执行很多
mov
到内存的命令,所以我尝试制作某种宏,它采用地址并以小尾端形式发出,因此:

#define EmitDword(x)\
{\
    _asm _emit (x & 0x000000FF) \
    _asm _emit ((x >> 8) & 0x000000FF) \
    _asm _emit ((x >> 16) & 0x000000FF) \
    _asm _emit ((x >> 24) & 0x000000FF) \
}
但是我在“第一个操作数”中得到了一个错误
内联汇编程序语法错误
其思想是,将变量的地址传递给宏,这样就可以将其直接发送到机器代码中,然后我可以这样做:

 #define EmitDword(x)\
 {\
        _asm _emit (x & 0x000000FF) \
        _asm _emit ((x >> 8) & 0x000000FF) \
        _asm _emit ((x >> 16) & 0x000000FF) \
        _asm _emit ((x >> 24) & 0x000000FF) \
 }

/* mov qword ptr [addr],reg  */
#define X64_MovToMem(addr,reg)\
{\
  _asm _emit 0x48\
  _asm _emit 0x89\ 
  _asm _emit reg\ 
  _asm _emit 0x25\
  EmitDword(addr)\ 
}

#define _rax 4
void test()
{
    DWORD64 someData;
    X64_MovToMem(&someData,_rax);
}
struct {
    void const *offset;
    unsigned short selector;
} const _read64ptr_ind = { _read64ptr, 0x33 };

unsigned long long
read64ptr(unsigned long long address) {
    unsigned long long value;
    _asm {
        push    DWORD PTR [address + 4]
        push    DWORD PTR [address]
        call    FWORD PTR [_read64ptr_ind]
        add     esp, 8
        mov     DWORD PTR [value], eax
        mov     DWORD PTR [value + 4], edx
    }
    return value;
}

是否有任何方法可以使用预处理器内联汇编来实现非常量值的发出?

很抱歉,但是您试图做的事情毫无意义

  • “在x86程序中插入一些x64操作码”-如果是x86程序,则不会运行x64操作码
  • “\u asm\u emit(x&0x000000FF)”-您是否阅读了emit的说明?您只能发出字节,不能发出C代码
  • “emit”-为什么您认为每4次写入1个字节(此代码无论如何都不会这样做)会比写入1次4个字节快
  • “有没有办法实现非常量值的发射”-如果您使用的是发射,那么您需要知道您试图写入的值当前存储在哪个寄存器中(这几乎是不可能完成的,因为每次代码更改时编译器可能使用不同的寄存器,而值甚至可能不在寄存器中)
我试图回顾一下你是如何写这篇文章来解决你原来的问题的。然而:

我意识到有一种倾向认为“asm更快”。但请记住,C代码会被翻译成汇编程序。编译器已经在生成asm代码,这几乎肯定比通过emit拼凑起来的代码要高效得多

如果使用64位指令将产生更好的代码(这当然是可能的),那么您应该构建一个64位可执行文件


如果你确信你可以创建比C编译器更有效的ASM代码,考虑创建一个完整的ASM例程,然后从C代码中调用它。注意你不能将X64汇编程序链接到你的x86程序。

< p>对不起,但是你想做的没有意义。
  • “在x86程序中插入一些x64操作码”-如果是x86程序,则不会运行x64操作码
  • “\u asm\u emit(x&0x000000FF)”-您读过emit的代码吗?您只能发出字节,不能发出C代码
  • “emit”-为什么您认为每4次写入1个字节(此代码无论如何都不会这样做)会比写入1次4个字节快
  • “有没有办法实现非常量值的发射”-如果您使用的是发射,那么您需要知道您试图写入的值当前存储在哪个寄存器中(这几乎是不可能完成的,因为每次代码更改时编译器可能使用不同的寄存器,而值甚至可能不在寄存器中)
我试图回顾一下你是如何写这篇文章来解决你原来的问题的。然而:

我意识到有一种倾向认为“asm更快”。但请记住,C代码会被翻译成汇编程序。编译器已经在生成asm代码,这几乎肯定比通过emit拼凑起来的代码要高效得多

如果使用64位指令将产生更好的代码(这当然是可能的),那么您应该构建一个64位可执行文件


如果你确信你可以创建比C编译器更有效的ASM代码,考虑创建一个完整的ASM例程,然后从C代码中调用它。注意你不能将X64汇编程序链接到你的x86程序。

你不需要在32位进程中使用64位代码来访问64位进程E。nEnvironment Block。您可以使用32位代码获取其地址,它位于32位地址空间内。如果您需要访问分配在32位地址空间之外的内存,则只需要使用64位代码,我认为Windows在32位进程中永远不会这样做

如果您确实需要在32位可执行文件中使用64位函数,那么有一种比使用
\u asm\u emit
更好的方法。首先要做的是在普通汇编中编写整个64位函数,并使用普通外部汇编程序进行汇编。例如,这里有一个函数可以从MA中的64位指针进行读取SM语法:

\u文本段
__read64ptr:
mov rax,[rsp+8]
mov-eax,[rax]
移动edx,[rax+4]
翻新
_文本结尾
终止
此简单函数将64位指针作为堆栈上的参数。位于指向的地址处的64位值放入EAX和EDX。此函数旨在使用32位远调用指令调用

请注意,返回值占用两个32位堆栈插槽,一个用于返回地址的32位偏移量,另一个用于选择器。尽管RETF指令在64位模式下执行,但默认情况下它使用32位堆栈大小(与64位near RET指令不同)并将与堆栈上保存的32位远返回地址一起正常工作

不幸的是,我们无法直接使用Visual Studio提供的工具使用此程序集文件。64位版本的MASM只创建64位对象文件,链接器不允许我们混合使用32位和64位对象文件。使用NASM并与Microsoft的链接器链接,应该可以将64位代码组装成32位对象,但这是p可能仅使用Microsoft的工具间接使用代码

为此,组装文件并手动将机器代码复制到位于
.text
部分的C数组中:

#pragma code_seg(push, ".text")
#pragma code_seg(pop)
char const __declspec(allocate(".text")) _read64ptr[] = {
    0x48, 0x8b, 0x44, 0x24, 0x08,   /* mov rax, [rsp + 8] */
    0x8b, 0x00,                     /* mov eax. [rax] */
    0x8b, 0x50, 0x04,               /* mov edx, [rax + 4] */
    0xcb                            /* retf */
};
要调用它,只需使用如下代码:

 #define EmitDword(x)\
 {\
        _asm _emit (x & 0x000000FF) \
        _asm _emit ((x >> 8) & 0x000000FF) \
        _asm _emit ((x >> 16) & 0x000000FF) \
        _asm _emit ((x >> 24) & 0x000000FF) \
 }

/* mov qword ptr [addr],reg  */
#define X64_MovToMem(addr,reg)\
{\
  _asm _emit 0x48\
  _asm _emit 0x89\ 
  _asm _emit reg\ 
  _asm _emit 0x25\
  EmitDword(addr)\ 
}

#define _rax 4
void test()
{
    DWORD64 someData;
    X64_MovToMem(&someData,_rax);
}
struct {
    void const *offset;
    unsigned short selector;
} const _read64ptr_ind = { _read64ptr, 0x33 };

unsigned long long
read64ptr(unsigned long long address) {
    unsigned long long value;
    _asm {
        push    DWORD PTR [address + 4]
        push    DWORD PTR [address]
        call    FWORD PTR [_read64ptr_ind]
        add     esp, 8
        mov     DWORD PTR [value], eax
        mov     DWORD PTR [value + 4], edx
    }
    return value;
}
间接