我在c:__asm__("mov $10, %rsi"); printf("%x")
中输入此代码,它打印a
。
我在gdb
调试它,发现结果存储int register esi
。
问题:为什么结果是esi
?c printf(“%x”),它打印什么?
回答
printf("%x")
试图获得第二个参数,但它不在那里,所以它只是读取应该出现的内存,找到存在的任何垃圾并将其打印出来。
简而言之:它是未定义的行为。
编辑:你看到相同的值作为esi
寄存器的原因,是这个值计算程序中的一些早期的(但最近的)计算的一部分,并储存在printf
试图读取相同的位置从。两个地点重合的事实纯粹是偶然的,在未定义的行为范围内。
它发现,它将视为一个无符号整数并打印十六进制代码(小写)(这是%x所做的)。 – Thilo 2013-04-23 08:32:16
@ybungalobill它如何知道地址应该在哪里?换句话说,它从哪里读取? – 2013-04-23 08:34:25
@Armin:这是“实现定义”。查看库/编译器的源代码,或者查阅您的编译器或ABI文档。 – 2013-04-23 08:35:42
当调用printf("%x")
时,会发生它需要的参数被推送到堆栈(以相反的顺序),并最终使用汇编命令call
调用该函数。当提供格式字符串"%x"
时,printf()
预计至少有一个参数在下面,所以它会读取堆栈上的下一个值,可能是任何东西......
所以这种行为实际上是未定义的,并且通常是利用的原因,因为您可能会损坏堆栈。
也许有点excourse关于这个话题。
不是将返回地址推入堆栈,而是一旦参数按相反顺序推入? – 2013-04-23 08:40:46
@SheerFish:通常(包括x86和amd64体系结构)它是'call'指令。 – ybungalobill 2013-04-23 08:42:07
我现在不是百分之百肯定,但我认为是这样......它必须在某个地方,以便ESP/RSP知道下一步该去哪里。但这是实施和操作系统的依赖... – 2013-04-23 08:43:04
- 1. 为什么下面的printf打印0x32
- 2. 打印 '%' 与C的printf/C++
- 3. 为什么printf不打印垃圾值?
- 4. Java printf不打印
- 5. \ x在打印中做什么
- 6. c - printf(“%s”)打印一个额外的@
- 7. C - printf(“%i”)打印一个额外的%
- 8. C printf不在线内打印?
- 9. printf()将不会打印字符串c
- 10. printf()打印垃圾字符
- 11. 为什么printf不在控制台上打印“操作员”?
- 12. 为什么换行时使用ld打印printf失败?
- 13. 为什么省略printf打印垃圾的参数?
- 14. 调用的printf打印
- 15. 为什么打印0(零)时没有在C printf格式“%#x”的前面加上“0x”?
- 16. Java-为什么它打印出null?
- 17. 它为什么打印整数
- 18. 程序集中的printf如何知道要打印什么?
- 19. 为什么write()在输出重定向的printf()之前打印?
- 20. 为什么这个long double打印不正确使用printf?
- 21. 为什么printf(“%%”)只打印一个百分号(%)符号?
- 22. 为什么我的printf打印错误的值?
- 23. 怎样的printf知道符号扩展后打印出什么
- 24. 为什么第三个printf会打印未定义的值?
- 25. 为什么printf“$ {array [@]} \ n”打印我数组的所有元素?
- 26. 使用printf打印size_t的正确方法是什么?
- 27. 这段代码有什么问题?事件printf未被打印
- 28. 将int打印为float时,printf的行为是什么?
- 29. PHP - 为什么不打印变量,尽管它打印文本?
- 30. c#中的打印序列是什么?
好问题!编辑:ybungalobill已经偷走了答案! – 2013-04-23 08:31:58
你是怎么确定结果(大概你的意思是printf的返回值,应该是2)存储在esi中? – nos 2013-04-23 09:18:15
'__asm __(“mov $ 10,%rsi”);'编辑'esi/rsi'值,我尝试了一些其他的值。 – sumous 2013-04-23 09:21:11