2013-04-23 126 views
5

我在c:__asm__("mov $10, %rsi"); printf("%x")中输入此代码,它打印a
我在gdb调试它,发现结果存储int register esi
问题:为什么结果是esic printf(“%x”),它打印什么?

+0

好问题!编辑:ybungalobill已经偷走了答案! – 2013-04-23 08:31:58

+0

你是怎么确定结果(大概你的意思是printf的返回值,应该是2)存储在esi中? – nos 2013-04-23 09:18:15

+0

'__asm __(“mov $ 10,%rsi”);'编辑'esi/rsi'值,我尝试了一些其他的值。 – sumous 2013-04-23 09:21:11

回答

11

printf("%x")试图获得第二个参数,但它不在那里,所以它只是读取应该出现的内存,找到存在的任何垃圾并将其打印出来。

简而言之:它是未定义的行为。

编辑:你看到相同的值作为esi寄存器的原因,是这个值计算程序中的一些早期的(但最近的)计算的一部分,并储存在printf试图读取相同的位置从。两个地点重合的事实纯粹是偶然的,在未定义的行为范围内。

+1

它发现,它将视为一个无符号整数并打印十六进制代码(小写)(这是%x所做的)。 – Thilo 2013-04-23 08:32:16

+0

@ybungalobill它如何知道地址应该在哪里?换句话说,它从哪里读取? – 2013-04-23 08:34:25

+1

@Armin:这是“实现定义”。查看库/编译器的源代码,或者查阅您的编译器或ABI文档。 – 2013-04-23 08:35:42

2

当调用printf("%x")时,会发生它需要的参数被推送到堆栈(以相反的顺序),并最终使用汇编命令call调用该函数。当提供格式字符串"%x"时,printf()预计至少有一个参数在下面,所以它会读取堆栈上的下一个值,可能是任何东西......
所以这种行为实际上是未定义的,并且通常是利用的原因,因为您可能会损坏堆栈。

也许有点excourse关于这个话题。

+0

不是将返回地址推入堆栈,而是一旦参数按相反顺序推入? – 2013-04-23 08:40:46

+0

@SheerFish:通常(包括x86和amd64体系结构)它是'call'指令。 – ybungalobill 2013-04-23 08:42:07

+0

我现在不是百分之百肯定,但我认为是这样......它必须在某个地方,以便ESP/RSP知道下一步该去哪里。但这是实施和操作系统的依赖... – 2013-04-23 08:43:04

相关问题