Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.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++ 打印特定地址的字节_C++_C_Assembly - Fatal编程技术网

C++ 打印特定地址的字节

C++ 打印特定地址的字节,c++,c,assembly,C++,C,Assembly,我有以下代码 intptr_t location = (intptr_t)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtReadFile"); printf("addr-> %p\n", location); 我得到以下输出: 0x00007FF9DE1FC120 为了查看“0x00007FF9DE1FC120”中的操作码,我使用了x64dbg/IDA 打印位于0x

我有以下代码

intptr_t location = (intptr_t)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtReadFile");
printf("addr-> %p\n", location);
我得到以下输出:

0x00007FF9DE1FC120
为了查看“0x00007FF9DE1FC120”中的操作码,我使用了x64dbg/IDA

打印位于0x00007FF9DE1FC120的20个字节时遇到问题

    for (int i = 0; i < 10; i++)
    {
        printf("|%x| ", (char)((location)+i));
    }
    printf("\n");
我希望得到这样的东西

|4C| |8B| |D1| |B8| |06| |00| |00| |00| |F6| |04|
我很乐意得到你的帮助,
谢谢

location
是一个整数类型
intptr\t location
。您将该整数截断为
char
并打印该整数值,在本例中打印指针值的低位字节

您需要将
位置
转换回指针。要访问单个字节(当值提升为更宽的
int
unsigned
时,扩展名为零),请使用
const unsigned char*
。C/C++严格的混叠规则允许通过<代码>未签名CHAR*<代码>读取任何对象的对象表示,作为一个特殊的例外。strong>例如,使用
constuint32\u t*
时,这并不是绝对安全的。

printf("|%x| ", ((const unsigned char*)location)[i] );

传递到printf会通过默认整数升级隐式转换为
int
。如果需要,可以使用
%hhx
告诉printf只打印该int的低位
无符号字符

在C语言中,可以使用
const unsigned char*charloc=(void*)位置简化强制转换。在C++11中,可以使用
避免两次写入类型
auto charloc=static_cast(位置)。在C中,<代码> Audio/Cuth>只是<代码> int >代码>,C++中的代码> VUL**/COD>不可以自由转换为其他指针类型。因此,如果要编写同时有效的C和C++的代码,请避免这些。

脚注1:

%x
被指定为采用
无符号整数
,但没有未定义的行为,因为标准允许同一整数类型的
有符号
无符号
版本与变量/无符号参数传递兼容,只要值在这两种类型中都可以表示。C17,C.5.5.2.2为C,6,类似于ISO C++语言的变量函数。(
unsigned char
确保了这一点,
signed char
可以提升为负值
int
值。)

显示GCC和clang即使使用
-Wall-Wextra-Wpedantic
,也不会对此发出警告,即使您使用
(int)charloc[i]
使其显式
int
,而不仅仅是一个提升结果


它还显示了编译器使用
movzx-esi,byte ptr[rbx]
load,从内存中加载一个扩展名为零的字节,作为printf的参数。编译器从您的版本生成的asm不会进行任何加载,因此您可能已经发现您没有得到想要的东西。(我假设你比C更了解汇编语言,因为有标记吗?

一个
intptr\u t
是一个有符号整数,它足够大,可以容纳指针

由于您希望查看该地址的数据,因此在本例中,您需要实际的指针:

unsigned char const *pos = (unsigned char const *)location;

for (int i=0; i<20; i++)
    printf("|%2.2x| ", pos[i]);
unsigned char const*pos=(unsigned char const*)位置;

对于(int i=0;iFor start,您可能希望取消对位置的引用:
printf(“|%x |”),(无符号字符)位置[i])
,并将转换说明符限制为1字节,例如
“|%hhx”
@Quimby:
位置是
intptr\t位置
,而不是指针。OP打印的是地址,而不是指向的数据。
((unsigned char*)location)[i]
会起作用(而且是严格的别名安全的)。传递到printf会通过默认整数提升隐式转换为
int
。@PeterCordes你是对的,我错过了这一点。@ALevy PeterCordes才是真正正确的:)“从技术上讲,%x想要的是无符号的int而不是int,所以这还是有点马虎。”根据C17§6.5.2.2 6“一种升级类型为有符号整数类型,另一种升级类型为相应的无符号整数类型,且值可在两种类型中表示;”,
printf()
看不出区别。@chux-Monica-谢谢,没有意识到标准对变量/非类型参数的不匹配做出了例外。
intptr\u t
足够大,可以容纳一个对象指针,而不一定是ProcAddress。@chux-Monica:对于可移植代码,这是正确的。在这种情况下,我们正在处理使用Windows,并且知道它足够大,可以容纳函数的地址。对于可移植代码,这会发生变化(但可能只是移植的一小部分)。但实际上,真正的可移植代码无法做到这一点。
printf("|%x| ", ((const unsigned char*)location)[i] );
const unsigned char *charloc = (const unsigned char*)location;
printf("|%x| ", charloc[i]);
unsigned char const *pos = (unsigned char const *)location;

for (int i=0; i<20; i++)
    printf("|%2.2x| ", pos[i]);