汇编书中“存于寄存器内的地址可用来指向内存的某个位置,即寻址”
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编书中“存于寄存器内的地址可用来指向内存的某个位置,即寻址”相关的知识,希望对你有一定的参考价值。
这句话怎么理解啊?是寄存器内的地址和内存中的一个地址之间的关系好想快捷方式与程序一样吗
准确地说,是寄存器间接寻址."存于寄存器内的地址",如寄存器BX,它的值是BX=0020H;这的0020H就可以是一个地址.
当这样做:MOV AX,[BX]的时候,这时的[BX]就可以指向内存的某个位置,即DS:0020H (注:DS是默认的段地址寄存器)
我觉得你的理解也有道理:通过快捷方式找到程序,和通过放在在寄存器内的地址找到相应的内存地址是一样的. 参考技术A 就是C里面的指针,内存里面的每个单元都有一个绝对的物理地址,就好像你家一样。现在我要去你家,就先在一个地方存放你的地址,以后要访问你家就方便了。
gdb 中的奇怪结果
【中文标题】gdb 中的奇怪结果【英文标题】:Strange results in gdb 【发布时间】:2012-02-09 04:33:07 【问题描述】:我正在阅读一本关于 asm 并使用 GDB 研究寄存器和内存的 C 书籍。 问题是,当我编译和反汇编完全相同的源代码时(实际上是使用随书 cd 提供的源文件),汇编指令看起来与书中的内容有很大不同。 这本书使用了 intel 风格的汇编,我将“set disassembly intel”放在 gdb 中,所以不是这样。只是说明的顺序不同,有些完全不同,还有一些其他的怪癖。
比如书中的eip寄存器中有一条mov指令:
(gdb) x/i $eip
mov DWORD PTR[ebp-4], 0x0
对应将变量i初始化为0,在一个for循环中(i = 0, i
但是,在我的 gdb 控制台中,断点位于同一位置(set break main; run)我看到了:
(gdb) x/i $eip
mov DWORD PTR[esp+0x1c], 0x0
注意它同时引用了一个不同的寄存器 - esp 而不是 ebp 如果我检查 esp 的值,它本身就是 0x1c。但是,如果我尝试检查 0x1c 或 esp+0x1c 处的内容,它会告诉我我无法查看这些地址
所以随着这本书的继续,我根本无法跟进,因为它开始跟踪 ebp、ebp-4 等中的内容,而在我的 asm 中似乎没有任何内容发生在 ebp 寄存器中
这本书写于 2008 年,所以我无法想象它已经过时了,以至于 gcc 或 gdb 的版本更改会带来如此重大的变化(或者是这样做的?)......是否有可能一些编译器优化或默认打开的东西会产生如此不同的结果?
提前致谢
编辑:奇怪。我尝试了每个建议,但没有任何效果。然后我做了 rm a.out 并重新编译,现在它工作正常(说明仍然与书不同,但我可以检查与书对应的地址;只要我能遵循相应的模式,一切都很好,不必是完全相同的asm,那只会让它太容易了!) 再次感谢您的所有帮助和建议。
【问题讨论】:
【参考方案1】:有一百万种事情可能导致这种情况。如果你在不同的架构上编译你的代码,我会期望这个(不,这甚至不一定意味着 32 位和 64 位——实际上任何不同的 CPU 架构都可以改变执行顺序,我将解释) .如果你用优化编译你的程序,它将改变执行的顺序以最好地利用你的 CPU 的管道。这可能意味着添加一些 NOOP 指令,或完全重新排序它们(当然,在合理范围内)。此外,一些 CPU 有多种做事方式,一种方式通常比另一种更快(想到英特尔 LOOP 指令——现代编译器像瘟疫一样避免这条指令,因为它很糟糕)。如果一个寄存器比另一个更有效,它将使用它。
故事的寓意:出于学习目的,作者和读者都需要禁用所有优化。还有额外的奖励积分:使用相同版本的 gcc 和相同的平台。
【讨论】:
感谢您的洞察力。这就是我想知道的,我怎样才能强制不进行优化。我知道确切的内存地址甚至指令可能因架构而异,这就是编译器的重点,但我很惊讶它是如此不同 - 即使遵循 asm 似乎是一个不同的程序(它是只不过是 main 中的一个 for 循环,所以很容易理解)实际上,虽然问题是它说值是在我无法检查的地址中初始化的(esp+0x1c),但情况不应该如此 @rootlickergcc -O0
(即字母 O 后跟数字 0)【参考方案2】:
看起来您编译的代码是使用-fomit-frame-pointers
编译的,这已成为 GCC-4.6 的默认设置。
尝试使用显式 -fno-omit-frame-pointer
构建。我希望结果看起来更接近书。
【讨论】:
【参考方案3】:这一切都将是平台和编译器特定的。恐怕你无能为力。
【讨论】:
谢谢。这本书和我一样使用 32 位英特尔。两者都使用 gcc 编译(我需要检查版本并更新 qeustion),运行 linux。这本书基于 Ubuntu(再次需要检查版本),我正在运行最新的 Arch 安装。我会假设使用相同的架构和相同的编译器(gcc)机器代码会是相同的,不是吗?无论哪种方式,我发现一个值被初始化为一个我无法检查的地址很奇怪,而且它被 $esp 引用也很奇怪,即堆栈指针...... 不,没有理由应该是一样的。您可以使用-O0
或-march=i386
。但它会完全不同也就不足为奇了。以上是关于汇编书中“存于寄存器内的地址可用来指向内存的某个位置,即寻址”的主要内容,如果未能解决你的问题,请参考以下文章