存储到堆栈地址的双字是不是会影响地址+0..3 或地址-0..3 处的字节?
Posted
技术标签:
【中文标题】存储到堆栈地址的双字是不是会影响地址+0..3 或地址-0..3 处的字节?【英文标题】:Does a dword store to a stack address affect bytes at address+0..3 or address-0..3?存储到堆栈地址的双字是否会影响地址+0..3 或地址-0..3 处的字节? 【发布时间】:2021-04-21 10:14:12 【问题描述】: 在 x86 架构(比如 32 位)中,地址是否只指向一个字节?意思是,如果我们查看地址 0x0000 0000 0000 FFFF 是不是只有一个字节?我认为答案是肯定的,但需要确认我想知道这条指令的值是如何存储的,movl %eax, -4(%rbp)
。我的理解是我们将堆栈中的值放在基指针的较低地址。
由于 eax 是 32 位,当我们进行操作时,它实际上是如何显示在堆栈上的?意思是,如果eax有0x0a0b0c0d,并且使用小端序是这个吗?
rbp[-4] 0d ; low byte at given address
rbp[-3] 0c
rbp[-2] 0b
rbp[-1] 0a ; dword ending here
还是这个?
rbp[-7] 0d
rbp[-6] 0c
rbp[-5] 0b
rbp[-4] 0a ; high byte at given address, dword ending here
或 其他的,因为我不明白?任何帮助都会很棒
【问题讨论】:
别想太多。加载和存储总是从多字节内存数据的最低(数字)地址计算和工作。向下增长的堆栈不会改变这一点。负位移寻址不会改变这一点。 【参考方案1】:每个字节都有自己的地址,所以从这个意义上说,地址 0x12345678 只有一个字节。但是,我们通常会说“地址 0x12345678 处的双字”。这意味着由地址 0x12345678、0x12345679、0x1234567a、0x1234567b 处的字节组成的 4 字节双字,最低有效在前。
所以这取决于您所说的“查看地址”是什么意思。例如,如果您要求调试器显示地址 0x12345678 的内容,并且它设置为显示双字,它将显示一个 4 字节双字,但这并不意味着该双字的所有 4 个字节都位于地址 0x12345678 .
因此,您对movl %eax, -4(%rbp)
的两个猜测中的第一个是正确的。对于大于一个字节的加载和存储,给定地址指向要访问的对象的最低地址字节。
请注意,这使得对齐计算工作得很好:对齐的双字是一个地址是 4 的倍数,因此双字地址的低 2 位为零。在 C 语言中((uintptr_t)&intvar) % 4 == 0
,对于 alignof(int) == 4。另一种方式意味着对于对齐的对象,低 n 位必须全为 1。
【讨论】:
【参考方案2】:是的,不是的。寻址粒度是一个字节,所以是的,地址0x0000 0000 0000 FFFF
指向一个字节,其前一个字节用0x0000 0000 0000 FFFE
寻址,其后一个字节用0x0000 0000 0001 0000
寻址。然而,我们也可以从同一个地址加载一个 16 位字,而不是一个字节。
例如,指令MOV AX,[0x0000_0000_0000_FFFF]
将从0x0000 0000 0000 FFFF
加载AL 和从0x0000 0000 0001 0000
加载AH。在这种情况下,0x0000 0000 0000 FFFF
正在处理一个词。类似地,更长的数据类型可以用相同的数字来处理(尽管在此架构中始终建议对齐,有时甚至是强制性的)。
如果EAX
包含值 0x0a0b0c0d
,则AL=0x0D
、AH=0x0C
等。
movl %eax, -4(%rbp)
别名 MOV [RBP-4],EAX
在 Intel 语法中,会将 32 位双字存储到地址 [RBP-4]
,即 AL=0x0D
转到 [RBP-4]
,AH=0x0C
转到 [RBP-3]
等。
【讨论】:
以上是关于存储到堆栈地址的双字是不是会影响地址+0..3 或地址-0..3 处的字节?的主要内容,如果未能解决你的问题,请参考以下文章
存储器的保护——《x86汇编语言:从实模式到保护模式》读书笔记20