【问题标题】:Understanding the "stack"理解“堆栈”
【发布时间】:2014-07-11 00:10:30
【问题描述】:

因此,当我们提到“栈顶”时,请记住它位于栈内存的底部。

我正在阅读有关 x86 ASM 的教程,它有这个。我真的无法理解这有什么意义。我认为它与一些硬件级别的事情有关,到目前为止,我对硬件一无所知。

有人可以解释一下吗?图表会非常有帮助,但也许只是解释为什么“堆栈顶部”意味着“堆栈底部”

【问题讨论】:

标签: assembly x86


【解决方案1】:

我绝对不会选择 x86 作为您的第一个汇编语言...但是它们几乎都有一个堆栈。

想象一沓便条卡,每张卡片上只能写一个便条。说一份杂货清单,一个说鸡蛋,另一个说牛奶另一个面包。所以你可以去看看最上面的,对我需要面包,拿到面包弃牌。下一个牛奶,对,去拿那个,丢弃卡片,等等。哦,我需要黄油,把它写在一张新卡片上,放在上面,然后去拿它,取下它,丢弃它。以此类推。

现在如果说你有 20 张牌,如果上面的牌编号为 0,那么下面的那张是 1,下面的那张是 2。或者如果上面的牌是 19,那么下面的那张是 18,以及然后17?不,只要每个关心编号规则的人都遵循规则,那么这并不重要。

我们为什么要关心卡片编号?因为该数字是用于该项目的内存地址。如果您从 0 到 N 编号,则您的堆栈在内存中增长,最旧的东西在 0,最新的东西在 N。或者您的堆栈可能从顶部向下增长,其中最旧的东西是堆栈中的最高地址和最新的东西在N处。只要每个人都知道规则,它就是任意的。

我们关心的另一个原因是某些处理器/许多处理器有办法跳过,我想查看向下的第三张卡,但是在查看时我无法删除它,我只能从堆栈顶部删除或添加。不过,您可以做的也是将第三张卡替换下来。为什么我们会关心做这样的事情?想想 C 函数中的局部变量,也许我的函数中有两个局部变量是整数。 C 是递归的,所以每次我调用该函数时,都需要再存储两个整数。堆栈非常适合。一旦我在函数中,我将两张空白卡片添加到堆栈中,如果我需要访问这些整数,则在运行该函数时,读取或写入它们我可以偷看或用具有一些新值的卡片替换这些卡片.当我退出该功能时,我取出两张牌并丢弃它们,以我到达那里时找到它的方式离开堆栈。堆栈在函数期间是临时存储的,但在某种程度上,我不在乎地址是什么,我只关心上面的两张卡是我的,我可以同时拿到它们,堆栈可能有 1000 张卡高或8745卡高无所谓我只关心前两个,我下面的所有卡都属于调用我的函数的函数。退出的每个函数都会清理属于它的卡片。

堆栈只是内存,并通过称为堆栈指针的指针寄存器指向。这使得我们不关心具体地址是什么,我们只关心它们与堆栈指针的关系。我们必须知道并遵循该处理器的规则或该处理器或环境的约定,才能知道使用哪种方式进行偏移,如果堆栈向下增长意味着 sp = sp - 3(locations) 将三个空白卡添加到堆栈中, sp+0 是顶部 sp+1 是堆栈中的下一个,依此类推。如果堆栈在地址空间中增长(不是那么常见,但有一些可以或可以做),那么 sp = sp + 3(locations) 就是您向堆栈添加 3 个新事物的方式,而 sp-1 是第一个下,等等。

现在不是计算的黑暗时代,我建议更好地学习 C 或某种编程语言,以任何语言编写程序,能够将问题分解为步骤并实施步骤以完成任务.然后 asm 只是将这些步骤分解为更小的步骤并按顺序执行这些步骤。我再次推荐除了 x86 之外的几乎任何东西作为第一个指令集,并且我建议使用指令集模拟器(模拟器或仿真器)而不是真正的硬件作为你的第一个汇编语言,一旦你开始掌握它,特别是调试你的asm 你会完全理解,尤其是如果你从一个更直接的指令集开始,然后再看 x86。 msp430、arm、pdp11(是的,我很认真)、avr 和其他一些是很好的第一指令集。但在深入学习 asm 之前,请先获得一定程度的 C 或类似的经验。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-23
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 2014-11-12
    • 2018-06-30
    相关资源
    最近更新 更多