二进制到ASCII在C ++和Grep之间有什么不同?

时间:2014-11-01 00:50:40

标签: c++ bash grep bin

我试图弄清楚如何在c / c ++程序的编译二进制文件中记录agument。以下是我的计划。我只想尽量简化

void f(char a,char b){}
int main(){f(12,23);}

为了能够实际阅读"二进制文件,我需要将其转换为某些ASCII"可表示"形成。我发现了

grep $'\xx' a.out

实际上使用a.out作为二进制文件,xx作为十进制ascii代码。但grep不能告诉我任何事情,因为它只会输出"二进制匹配"。如果我强行打印出' -a'它会打印出所有内容。虽然,我可以使用-c选项来查看它们中有多少:

grep $'\12' b.out (I renamed the file) ==> 4
grep $'\23' b.out                      ==> 3

但是为了研究某些东西,我需要确切的位置。所以我编写了另一个程序,它基本上打印出ASCII加入char。

#include<iostream>
using namespace std;
int main(){char c;
    while(cin>>c)cout<<(int)c<<' ';}

但是当我运行以下命令时,结果实际上并不匹配:

./a.out<./b.out|tr ' ' '\n'|grep -c '^12$' ==> 0
./a.out<./b.out|tr ' ' '\n'|grep -c '^23$' ==> 4

我想知道我在测试程序中写错了什么?或者grep是否有某种特殊的机制(比如不是逐字节)?哪一个是正确的?或者有人可以直接给我答案: &#34; 1,2,3,4&#34; in func(1,2,3,4)以二进制

记录

EDT1 感谢您的建议,我使用了&#34; od -tu1&#34;取代我的测试程序非常好。并且我稍微增强了我的测试程序,以便争论更明显,数字不会消失&#34;:

void f(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j,int k,int l,int m,int n,int o,int p,int q,int r,int s,int t){a+=b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t;}
int main(){f(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);}

通过更改这些参数并使用&#34; diff&#34;命令,我终于找到了这些数字在二进制文件中的位置:

0002560  68  36 104  19   0   0   0 199  68  36  96  18   0   0   0 199
0002600  68  36  88  17   0   0   0 199  68  36  80  16   0   0   0 199
0002620  68  36  72  15   0   0   0 199  68  36  64  14   0   0   0 199
0002640  68  36  56  13   0   0   0 199  68  36  48  12   0   0   0 199
0002660  68  36  40  11   0   0   0 199  68  36  32  10   0   0   0 199
0002700  68  36  24   9   0   0   0 199  68  36  16   8   0   0   0 199
0002720  68  36   8   7   0   0   0 199   4  36   6   0   0   0  65 185
0002740   5   0   0   0  65 184   4   0   0   0 185   3   0   0   0 186
0002760   2   0   0   0 190   1   0   0   0 191   0   0   0   0 232 234

如你所见,19~9都清楚地写在这里。但是从8到0,事情开始以一种不可理解的方式发生变化。数字之间的位移变得越来越小。而且我也不明白它们之间的数字是什么(我明白0是&#34; int&#34;部分(小端?))。这些数字是否代表某种地址?#34;插件&#34;?所以根据不同的位置他们是不同的,他们的长度也不同?

1 个答案:

答案 0 :(得分:2)

哇。你的问题表明你愿意尝试并渴望学习,但是在堆栈溢出问题中通常会发生更多的事情要理解。

首先,grep是一个非常强大的工具,但不适合您的任务。您将对od更感兴趣,它将为您提供文件的原始二进制转储。 (查看其标志以查看如何以十六进制,十进制或甚至纯二进制形式输出。)

接下来,如果你想编写一个二进制文件,如果你用可执行文件写它,你将会看到一堆东西。除了您要存储的变量外,可执行文件还包含您正在编译的所有代码。隔离代表你的变量的(可能是)四个字节是非常困难的,并且你想要读取a.out可执行文件背后的格式以便能够做到这一点。

编写一个能编写二进制文件的C程序就简单得多了,例如:

#include <stdio.h>
int main() {
    int one;
    int two;
    int three;
    int four;
    one = 1;
    two = 2;
    three = 3;
    four = 4;
    FILE* fp = fopen("test.dat", "wb");
    fwrite(&one, sizeof(int), 1, fp); 
    fwrite(&two, sizeof(int), 1, fp); 
    fwrite(&three, sizeof(int), 1, fp); 
    fwrite(&four, sizeof(int), 1, fp); 
    fclose(fp);
    return 0;
}

还有很多其他的方法来编写相同的代码,一些优秀的人可以纠正我所犯的任何明显的错误(因为我没有使用编译器编写C语言已经有一段时间了),但是应该只写4个整数。

最后,快速回答您的问题。假设int是32位,那么您将以二进制形式写入这些数字。你必须抬头看看#big-endian vs. little-endian&#34;了解下一部分,但根据您的架构,您将成为一个或另一个。 Big-endian更直观,所以我会回答使用这个概念。

数字存储为32位二进制值。 (int中的第一位是符号位。如果它是1,则该值为负,并且您必须查找&#34;两个补码&#34;以便理解在你的情况下,对于&#34; 1,2,3,4和#34;,只有最后3位才重要,所以你会看到很多0:

1: 00000000 0000000 00000000 00000001
2: 00000000 0000000 00000000 00000010
3: 00000000 0000000 00000000 00000011
4: 00000000 0000000 00000000 00000100

注意,这变得非常笨重,所以我们倾向于使用十六进制。使用它,您可以用2个字符表示每个8位字节。在十六进制中,您的答案是:

1:   00 00 00 01
2:   00 00 00 02
3:   00 00 00 03
4:   00 00 00 04
17:  00 00 00 11
255: 00 00 00 FF

你有很多学习要做,但要坚持下去!我认为你是多么渴望实验。希望这会有所帮助。