如何对内存中的地址执行十六进制内存转储?
How can I perform a hex memory dump on an address in memory?
我正在尝试为我的计算机机器组织编写一个 C++ 程序 class,我在其中对存储在内存中的某个地址执行十六进制内存转储。我真的不明白内存转储是什么,而且我对编写 C++ 还很陌生。我的问题是:
- 如何创建一个方法,该方法采用两个参数,并在其中指定内存中的地址?
- 如何进一步修改这些参数以指定恰好 4 个字节长的字地址?
- 我怎样才能将这些地址转换成十六进制值?
我知道这很多,但感谢您的任何建议。
对于任何需要它的人,这是我到目前为止的代码:
#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++ 的同时编写 Hex dump 工具:
- 从简单的事情开始:
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output character
std::cout << test[0] << '\n';
}
输出:
M
- 打印 hex-value 而不是字符:
#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
注:
char
的流输出运算符旨在打印一个字符(当然)。 unsigned
还有另一个流输出运算符,它更适合。为了实现它的使用,必须将 char
转换为 unsigned
.
但要做好准备:C++ 标准不强制要求 char
是有符号的还是无符号的——这个决定留给编译器供应商。为了安全起见,'char'先转换为'unsigned char',然后再转换为unsigned
。
- 打印字符所在变量的地址:
#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
注:
const char*
有一个流输出运算符,用于打印 (zero-terminated) 字符串。这不是预期的。因此,转换为 const void*
的(丑陋的)技巧是必要的,它会触发另一个更适合的流输出运算符。
- 如果数据不是 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
注:
有I/O manipulators可用于修改(某些)流输出运算符的格式。
- 现在,将它们放在一起(在循环中)然后瞧瞧:hex-dump。
#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
- 让它好看:
#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
- 让它成为一个函数:
#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
注:
(const char*)&n
可能看起来有点冒险。事实上,指针的转换总是充其量是不必要的。但是,对于转储工具,这是访问任意数据字节的最简单方法。 (这是标准明确允许的罕见情况之一。)
可以在
中找到更好的 hexdump
SO: How would I create a hex dump utility in C++?
(我事先推荐了 OP)。
我正在尝试为我的计算机机器组织编写一个 C++ 程序 class,我在其中对存储在内存中的某个地址执行十六进制内存转储。我真的不明白内存转储是什么,而且我对编写 C++ 还很陌生。我的问题是:
- 如何创建一个方法,该方法采用两个参数,并在其中指定内存中的地址?
- 如何进一步修改这些参数以指定恰好 4 个字节长的字地址?
- 我怎样才能将这些地址转换成十六进制值?
我知道这很多,但感谢您的任何建议。
对于任何需要它的人,这是我到目前为止的代码:
#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++ 的同时编写 Hex dump 工具:
- 从简单的事情开始:
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output character
std::cout << test[0] << '\n';
}
输出:
M
- 打印 hex-value 而不是字符:
#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
注:
char
的流输出运算符旨在打印一个字符(当然)。 unsigned
还有另一个流输出运算符,它更适合。为了实现它的使用,必须将 char
转换为 unsigned
.
但要做好准备:C++ 标准不强制要求 char
是有符号的还是无符号的——这个决定留给编译器供应商。为了安全起见,'char'先转换为'unsigned char',然后再转换为unsigned
。
- 打印字符所在变量的地址:
#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
注:
const char*
有一个流输出运算符,用于打印 (zero-terminated) 字符串。这不是预期的。因此,转换为 const void*
的(丑陋的)技巧是必要的,它会触发另一个更适合的流输出运算符。
- 如果数据不是 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
注:
有I/O manipulators可用于修改(某些)流输出运算符的格式。
- 现在,将它们放在一起(在循环中)然后瞧瞧:hex-dump。
#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
- 让它好看:
#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
- 让它成为一个函数:
#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
注:
(const char*)&n
可能看起来有点冒险。事实上,指针的转换总是充其量是不必要的。但是,对于转储工具,这是访问任意数据字节的最简单方法。 (这是标准明确允许的罕见情况之一。)
可以在
中找到更好的 hexdump
SO: How would I create a hex dump utility in C++?
(我事先推荐了 OP)。