C程序的命令行输入(使用Perl的'print'命令)

Command line input to a C program (using 'print' command of Perl)

我很难理解 print Perl 命令解释十六进制值的方式。我正在使用一个只有 8 行的非常简单的程序来演示我的问题。以下带有 gdb 的代码将详细解释我的问题:

anil@anil-Inspiron-N5010:~/Desktop$ gcc -g code.c
anil@anil-Inspiron-N5010:~/Desktop$ gdb -q ./a.out
Reading symbols from ./a.out...done.
(gdb) list
1   #include <stdio.h>
2   
3   int main(int argc, char* argv[])
4   {
5       int i;
6       for (i =0; i<argc; ++i)
7           printf ("%p\n", argv[i]);
8       return 0;
9   }
(gdb) break 8
Breakpoint 1 at 0x40057a: file code.c, line 8.
(gdb) run $(perl -e 'print "\xdd\xcc\xbb\xaa"') $(perl -e 'print "\xcc\xdd\xee\xff"')
Starting program: /home/anil/Desktop/a.out $(perl -e 'print "\xdd\xcc\xbb\xaa"') $(perl -e 'print "\xcc\xdd\xee\xff"')
0x7fffffffe35d
0x7fffffffe376
0x7fffffffe37b

Breakpoint 1, main (argc=3, argv=0x7fffffffdfe8) at code.c:8
8       return 0;
(gdb) x/2x argv[1]
0x7fffffffe376: 0xaabbccdd  0xeeddcc00

在上面显示的行中,我使用了 gdb 来调试程序。作为命令行参数,我传递了两个(十六进制)参数(不包括程序本身的名称):\xdd\xcc\xbb\xaa\xcc\xdd\xee\xff。由于 little-endian 架构,这些参数应该被解释为 0xaabbccdd0xffeeddcc 但正如您所看到的,上面显示的调试的最后一行显示 0xaabbccdd0xeeddcc00。为什么会这样?我错过了什么??这也发生在其他一些争论中。我请求你帮助我。

PS:2^32 = 4294967296 和 0xffeeddcc = 4293844428 (2^32 > 0xffeeddcc)。不知道还有没有联系。

您将字符串打印为数字让自己感到困惑。在小端架构中,在四字节值(例如 0xDDCCBBAA)中,字节从起始地址开始按 从左到右 编号。

那么让我们看一下调试器命令的输出:

(gdb) x/2x argv[1]
0x7fffffffe376: 0xaabbccdd  0xeeddcc00

逐字节查看,它将是:

0x7fffffffe376: dd
0x7fffffffe377: cc
0x7fffffffe378: bb
0x7fffffffe379: aa

0x7fffffffe37a: 00  # This NUL terminates argv[1]
0x7fffffffe37b: cc  # This address corresponds to argv[2]
0x7fffffffe37c: dd
0x7fffffffe37d: ee

这并不出乎意料,不是吗?

您可能想使用类似这样的方法以十六进制显示参数:

x/8bx argv[1]

(这将显示 8 bytes in hexadecimal)

命令行参数是以 NUL 结尾的字符串。

参数 argv[1] 是指向以 NUL 结尾的字符串的第一个字符的指针。

7FFFFFFFE376  DD CC BB AA 00

argv[2] 是指向以 NUL 结尾的字符串的第一个字符的指针。

7FFFFFFFE37B  CC DD EE FF 00

如果你注意的话,你会发现它们恰好在内存中一个接一个地出现。

7FFFFFFFE376  DD CC BB AA 00 CC DD EE FF 00

您要求打印从 argv[1]

开始的两个(32 位)整数
7FFFFFFFE376  DD CC BB AA 00 CC DD EE FF 00
              ----------- -----------
               0xAABBCCDD 0xEEDDCC00

要使 x/2x 正确,您需要使用

perl -e'print "\xdd\xcc\xbb\xaa\xcc\xdd\xee\xff"'
   -or-
perl -e'print pack "i*", 0xaabbccdd, 0xffeeddcc'

对于您传递的参数,您需要使用

(gdb) x argv[1]
0x3e080048cbd:  0xaabbccdd
(gdb) x argv[2]
0x3e080048cc2:  0xffeeddcc