我试图弄清楚如何在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;?所以根据不同的位置他们是不同的,他们的长度也不同?
答案 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
你有很多学习要做,但要坚持下去!我认为你是多么渴望实验。希望这会有所帮助。