简体   繁体   English

ASM堆栈使用情况

[英]ASM Stack Usage

As far as I understand it, the stack can be used store data when you need to implement function or just run out of registers to use. 据我所知,当你需要实现函数或只是用完寄存器时,堆栈可用于存储数据。 The question I have is what piece of memory is the stack that is being used generally. 我的问题是通常使用的堆栈是什么内存。 I am getting the impression that this is dependent on the prefetch process and other factors. 我的印象是这取决于预取过程和其他因素。 Also at what point is the stacking being loaded back into RAM. 此外,在什么时候堆叠被加载回RAM。

Every process has threads and every thread has a stack. 每个进程都有线程,每个线程都有一个堆栈。 Each process has its own space called Process Address Space. 每个进程都有自己的空间,称为进程地址空间。 The threads allocate their stack in this process address space. 线程在此进程地址空间中分配其堆栈。 This space is a virtual space, meaning say a process gets 4 gb of process space, it might not always be on the RAM. 这个空间是一个虚拟空间,意味着一个进程获得4 GB的进程空间,它可能并不总是在RAM上。 It might be paged out to secondary memory when other process need RAM. 当其他进程需要RAM时,可能会将其分页到辅助内存。 Basically, you can assume that stack is a piece of memory managed by the OS by moving between secondary memory, RAM, cache etc, to optimize for best read/write times. 基本上,您可以假设堆栈是由OS管理的一块内存,通过在辅助内存,RAM,缓存等之间移动来优化最佳读/写时间。

I have mostly worked on windows and the above statements hold good for windows. 我主要在windows上工作,上面的语句适用于windows。 I am unsure about other operating systems. 我不确定其他操作系统。

Yes, the stack is used when you need temporary storage. 是的,当您需要临时存储时使用堆栈。 that could be as simple as storage for the duration of a function, or as mentioned when you run out of registers and need to evict one to repurpose it. 这可能就像函数持续时间的存储一样简单,或者当你用完寄存器并且需要驱逐一个以重新调整它时提到。

Dont get caught up in too much more than simply understanding how the instruction set/hardware works. 不要仅仅了解指令集/硬件的工作原理。 Generally called push and pop, these instructions generally take a register, usually a dedicated stack pointer register, which contains and address in ram. 通常称为push和pop,这些指令通常采用寄存器,通常是专用的堆栈指针寄存器,它包含ram中的地址。 When a push happens the address in that register, the stack pointer, is used to write/push that data into ram and the stack pointer register contents, a ram address, is adjusted accordingly. 当推送发生时,该寄存器中的地址(堆栈指针)用于将该数据写入/推入ram,并且相应地调整堆栈指针寄存器内容(ram地址)。 This all done by hardware based on using that instruction. 这一切都是由基于使用该指令的硬件完成的。 Pop the other way, ram is read based on the stack pointer address and flavor of pop instruction, contents of ram are placed somewhere based on the flavor of pop instruction and the stack pointer register contents are adjusted accordingly. 另一种方式是,基于堆栈指针地址和pop指令的风格读取ram,ram的内容根据pop指令的风格放置在某处,并相应地调整堆栈指针寄存器内容。

What ram address is used and why? 使用什么ram地址,为什么? Which is what I think you are asking. 这就是我认为你在问的问题。 Well that is up to the system designers usually, the folks taking ram in a system and dividing it up between program, data, heap and stack. 嗯,这通常取决于系统设计人员,人们在系统中占用ram并在程序,数据,堆和堆栈之间进行划分。 Often you see that if you have a single linear chunk of ram you are working with the lower (address) portion of that ram has the program itself, the instructions, just on top of that is the data used by that program, then the remainder of the memory is this no mans land. 通常你会看到,如果你有一个线性的ram块你正在使用该ram的较低(地址)部分有程序本身,指令,就在那之上是该程序使用的数据,然后是剩余的记忆是这个没有人的土地。 From the bottom of that memory toward the top is often where the heap lives. 从内存的底部到顶部通常是堆的所在。 The compiler doesnt know how much heap is needed for mallocs, only the programmer does. 编译器不知道malloc需要多少堆,只有程序员才需要。 The stack often begins at the top of this open space and grows down, each thing you push on the stack is pushed onto the bottom of the last thing you pushed on the stack and it grows down. 堆栈通常从这个开放空间的顶部开始并向下扩展,你在堆栈上推送的每个东西都被推到你在堆栈上推送的最后一个东西的底部并且它会向下扩展。 There is a very real risk of the stack and heap colliding and that is the job of the programmer (usually, some languages/compilers burn a lot of extra code to try to prevent it if you ask). 堆栈和堆冲突存在非常真实的风险,这是程序员的工作(通常,一些语言/编译器会烧掉大量额外的代码,以便在您提出要求时尝试阻止它)。 So generally the stack is co-located with the heap which is next door to the data and bss areas. 因此,通常堆栈与数据和bss区域隔壁的堆位于同一位置。 Certaily this is not always the case, in some embedded systems you have your program in rom, and data and heap (if you are brave/crazy enough to use heap in an embedded system) are in a section of ram, and the stack might be in a separate section of ram, not next to the data/heap ram. Certaily情况并非总是这样,在某些嵌入式系统中,你的程序在rom中,而数据和堆(如果你足够勇敢/疯狂到足以在嵌入式系统中使用堆)都在ram的一部分中,而堆栈可能在ram的单独部分中,而不是在data / heap ram旁边。 maybe because that ram is faster for example. 也许是因为那个公羊比较快。 A good example of this is the gameboy advance, there is a 256K memory that is off chip and slower for general purpose and an on chip internal 32k that is much faster that is a good place to put your stack (and speed critical code). 一个很好的例子就是游戏玩家的进步,有一个256K的内存是片外的,而且通用速度较慢,片上内部的32k速度要快得多,这是放置堆栈(和速度关键代码)的好地方。 the rom containing the program itself (with some hardware accelleration to make it not painfully slow). 包含程序本身的rom(加上一些硬件使其不会慢慢变慢)。 Sometimes you have processors like the 6502 where the stack instructions operate on a specific area of ram only, 256 locations I think at address 0x200 or something like that, designed into the hardware that way. 有时你有像6502这样的处理器,其中堆栈指令只在ram的特定区域上运行,我认为在地址0x200处有256个位置或类似的东西,以这种方式设计到硬件中。 On chip not off. 芯片没有关闭。 some processors like the ARM in ARM mode, dont have a stack pointer, any register can be used, and there isnt a push and pop, they are aliases for a flavor of general purpose load and store instructions. 一些处理器,如ARM模式下的ARM,没有堆栈指针,可以使用任何寄存器,并且没有推送和弹出,它们是通用加载和存储指令的别名。 By convention a particular register is often reserved/used by the compiler as the stack pointer, but it is not required like it is for other processors. 按照惯例,编译器通常将特定寄存器保留/用作堆栈指针,但不像其它处理器那样需要它。 Granted other arm instruction sets like thumb and thumb2, to reduce the instruction size remove the general purpose nature and hardcode the conventional r13 as the stack pointer, so for those modes you dont have a choice, you get r13 and you dont use a general purpose instruction you specifically use the push and pop instructions. 授予拇指和拇指2等其他手臂指令集,减少指令大小,删除通用性质,并将传统r13硬编码为堆栈指针,因此对于那些模式你没有选择,你得到r13而你不使用通用指示您专门使用推送和弹出指令。

Take all of this and place it in the windows or linux or other multi threaded/tasking operating system world. 把所有这些都放在windows或linux或其他多线程/任务操作系统世界中。 Nothing changes, the processor does not re-purpose its instruction set just for an operating system on the fly, you get the same set of instructions no matter what software you are running on that processor. 没有任何改变,处理器不会仅仅为操作系统重新设置其指令集,无论您在该处理器上运行什么软件,都可以获得相同的指令集。 What the operating system does is us an MMU, to make each program have the illusion of having a relatively small fixed amount of memory where the program space, data space, heap and stack live. 操作系统的作用是使用MMU,使每个程序都具有在程序空间,数据空间,堆和堆栈中存在相对较小的固定内存量的错觉。 The MMU gives the programs the illusion of all having the same address space, all programs for example may think that their program starts at address 0x8000, you cant have all programs live at one address, 0x8000 is a virtual address, the mmu maps it to a physical address and each program has a different set of physical addresses. MMU为程序提供了所有具有相同地址空间的错觉,例如所有程序都可能认为它们的程序从地址0x8000开始,你不能让所有程序都在一个地址,0x8000是一个虚拟地址,mmu将它映射到物理地址,每个程序都有一组不同的物理地址。 When the operating system switches to the next task/program/thread it saves your stack pointer and the other registers, and loads the registers for the next program (tickles the mmu) and gives it some time on the processor, where it also thinks it has its own flat memory space with program space, data space, heap and stack. 当操作系统切换到下一个任务/程序/线程时,它会保存您的堆栈指针和其他寄存器,并加载下一个程序的寄存器(勾选mmu)并在处理器上给它一些时间,它也认为它有自己的平面内存空间,包括程序空间,数据空间,堆和堆栈。

The bulk of understanding about a stack is looking at the instruction set. 关于堆栈的大量理解是查看指令集。 The rest of the story is how is the address the stack pointer is chosen which can vary based on the platform, operating system and compilers. 故事的其余部分是如何选择堆栈指针的地址,它可以根据平台,操作系统和编译器而变化。 In a lot of cases the linker script or link process has a user defined rule for that. 在很多情况下,链接描述文件或链接进程具有用户定义的规则。 You as the programmer/user may not realize you are in control of that as you probably just use the compiler default, but for the popular compilers (well linkers) you have the choice to change it. 您作为程序员/用户可能没有意识到您可以控制它,因为您可能只使用编译器默认值,但对于流行的编译器(井链接器),您可以选择更改它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM