如何对内存中的地址执行十六进制内存转储



我正试图为我的计算机机器组织类编写一个C++程序,在该程序中,我对存储在内存中的某个地址执行十六进制内存转储。我真的不明白什么是内存转储,而且我对编写C++还很陌生。我的问题是:

  1. 如何创建一个接受两个参数的方法,它们在其中指定内存中的地址
  2. 我如何进一步修改这些参数以指定一个正好为4字节长的字地址
  3. 如何将这些地址转换为十六进制值

我知道这是很多,但谢谢你的任何建议。

对于任何需要它的人,这里是我迄今为止的代码:

#include <stdio.h>
// Create something to do the methods on
char array[3] = {'a', 'b', 'c'};
void mdump(char start, char end){
// Create pointers to get the address of the starting and ending characters
char* pointer1 = (char *)& start;
char* pointer2 = (char *)& end;
// Check to see if starting pointer is in lower memory than ending pointer
if(pointer1 < pointer2){
printf("Passed");
}
else{
printf("Failed");
}
// Modify both the arguments so that each of them are exactly 4 bytes
// Create a header for the dump
// Iterate through the addresses, from start pointer to end pointer, and produce lines of hex values
// Declare a struct to format the values
// Add code that creates printable ASCII characters for each memory location (print "cntrl-xx" for values 0-31, or map them into a blank)
// Print the values in decimal and in ASCII form
}
int main(){
mdump(array[0], array[2]);
return 0;
}

如何在学习C++时编写十六进制转储工具:

  1. 从简单的事情开始:
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output character
std::cout << test[0] << 'n';
}

输出:

M

coliru 上的现场演示


  1. 打印十六进制值而不是字符:
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output a character as hex-code
std::cout << std::hex << test[0] << 'n'; // Uh oh -> still a character
std::cout << std::hex << (unsigned)(unsigned char)test[0] << 'n';
}

输出:

M
4d

coliru 上的现场演示

注:

char的流输出运算符用于打印字符(当然(。对于CCD_ 2,还有另一个流输出运算符更适合。为了实现它的使用,必须将char转换为unsigned

但要做好准备:C++标准并没有规定char是有符号的还是无符号的——这个决定权留给编译器供应商。为了安全起见,"char"首先转换为"unsigned char",然后转换为unsigned


  1. 用以下字符打印变量的地址:
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output an address
std::cout << &test[0] << 'n'; // Uh oh -> wrong output stream operator
std::cout << (const void*)&test[0] << 'n';
}

输出:

My sample data
0x7ffd3baf9b70

coliru 上的现场演示

注:

const char*有一个流输出运算符,用于打印(零终止(字符串。这不是我们想要的。因此,强制转换为const void*的(丑陋的(技巧是必要的,它触发了另一个更适合的流输出运算符。


  1. 如果数据不是2位十六进制怎么办
#include <iomanip>
#include <iostream>
int main()
{
// output character as 2 digit hex-code
std::cout << (unsigned)(unsigned char)'x6' << 'n'; // Uh oh -> output not with two digits
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< (unsigned)(unsigned char)'x6' << 'n';
}

输出:

6
06

coliru 上的现场演示

注:

有一些I/O操纵器可用于修改(某些(流输出运算符的格式。


  1. 现在,将所有内容放在一起(循环(,瞧:一个十六进制转储
#include <iomanip>
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output an address
std::cout << (const void*)&test[0] << ':';
// output the contents
for (char c : test) {
std::cout << ' '
<< std::hex << std::setw(2) << std::setfill('0')
<< (unsigned)(unsigned char)c;
}
std::cout << 'n';
}

输出:

0x7ffd345d9820: 4d 79 20 73 61 6d 70 6c 65 20 64 61 74 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

coliru 上的现场演示


  1. 让它变得漂亮:
#include <algorithm>
#include <iomanip>
#include <iostream>
int main()
{
char test[32] = "My sample data";
// hex dump
const size_t len = sizeof test;
for (size_t i = 0; i < len; i += 16) {
// output an address
std::cout << (const void*)&test[i] << ':';
// output the contents
for (size_t j = 0, n = std::min<size_t>(len - i, 16); j < n; ++j) {
std::cout << ' '
<< std::hex << std::setw(2) << std::setfill('0')
<< (unsigned)(unsigned char)test[i + j];
}
std::cout << 'n';
}
}

输出:

0x7fffd341f2b0: 4d 79 20 73 61 6d 70 6c 65 20 64 61 74 61 00 00
0x7fffd341f2c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

coliru 上的现场演示


  1. 使其成为一个函数:
#include <algorithm>
#include <iomanip>
#include <iostream>
void hexdump(const char* data, size_t len)
{
// hex dump
for (size_t i = 0; i < len; i += 16) {
// output an address
std::cout << (const void*)&data[i] << ':';
// output the contents
for (size_t j = 0, n = std::min<size_t>(len - i, 16); j < n; ++j) {
std::cout << ' '
<< std::hex << std::setw(2) << std::setfill('0')
<< (unsigned)(unsigned char)data[i + j];
}
std::cout << 'n';
}
}
int main()
{
char test[32] = "My sample data";
std::cout << "dump test:n";
hexdump(test, sizeof test);
std::cout << "dump 4 bytes of test:n";
hexdump(test, 4);
std::cout << "dump an int:n";
int n = 123;
hexdump((const char*)&n, sizeof n);
}

输出:

dump test:
0x7ffe900f4ea0: 4d 79 20 73 61 6d 70 6c 65 20 64 61 74 61 00 00
0x7ffe900f4eb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
dump 4 bytes of test:
0x7ffe900f4ea0: 4d 79 20 73
dump an int:
0x7ffe900f4e9c: 7b 00 00 00

coliru 上的现场演示

注:

(const char*)&n看起来可能有点冒险。事实上,指针的转换总是不必要的。然而,对于转储工具来说,这是访问任意数据字节的最简单方法。(这是标准明确允许的罕见情况之一。(



SO中可以找到一个更好的十六进制转储:我该如何在C++中创建一个十六进制转储实用程序
(我事先推荐了OP(。

最新更新