【问题标题】:x86_64-linux-gnu: Why is stack pointer subtracted from?x86_64-linux-gnu:为什么要减去堆栈指针?
【发布时间】:2018-02-11 21:22:50
【问题描述】:

我正在将下面的 sn-p 编译成程序集

void function(int a, int b, int c) {
   char buffer1[5];
   char buffer2[10];
}

void main() {
  function(1,2,3);
}

这是function的程序集sn-p

function:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $48, %rsp ; why is 48 being subtracted from the stack pointer?
    movl    %edi, -36(%rbp)
    movl    %esi, -40(%rbp)
    movl    %edx, -44(%rbp)
    movq    %fs:40, %rax
    movq    %rax, -8(%rbp)
    xorl    %eax, %eax

我在 64 位机器上运行它,所以我认为三个 8 字节字足以容纳 buffer1buffer2

【问题讨论】:

  • 对齐可能是个问题。
  • What is the direction of stack growth in most modern systems?Why do stacks typically grow downwards? 的可能重复项,请参阅 What is x86_64 red zone。您应该重新考虑接受以下答案。我认为它可以改进,通过标记为已接受,您表示您不想要更多[可能更好]的答案。
  • 以上 jww 假设您的问题是“为什么向下,而不是向上?”另一个问题可能是“为什么要改变,而不是保持不变?”您谈论大小的事实指向另一个但不清楚的问题。请解释你的问题是什么。也许通过描述你所期待的替代方案。

标签: c linux assembly x86-64


【解决方案1】:

乍一看,这似乎是内存对齐问题。 This question 详细介绍,我会特别注意 joshperry 的回答:https://stackoverflow.com/a/381368

维基百科在这里也谈到了这一点:Data structure alignment

简而言之,char buffer1[5] 将创建两个 64 字节的字(字符 1-4 和 5+)。如果没有,那么每次您引用buffer2 时,系统都必须执行至少两次操作才能获得buffer2 的正确起点。

【讨论】:

  • 五个字节的数组需要五个字节。它可能被放置在一个不错的 64 位边界上,并且很可能不会在它之后的三个字节中放置任何内容(使其成为下一个数组的偶数 8 个字节),但它不会像拆分数组的元素一样那。除非您使用char 为 16 位的系统?
  • a char 是 C 定义的一个字节,但 char 指针 不是。 char 数组是一个 char 指针,在 64 位 CPU 上是 64 位。
  • 明确地说,我不是肯定我的答案是正确的,但乍一看我认为这是内存对齐问题.编译器处理 5 字符数组不同于处理 5 个单独的字符
  • 啊,数组不是不是指针。它可以衰减到指向其第一个元素的指针,但数组本身是单个连续对象。
  • 我的理解是指向 5 字符内存块的指针大致相当于 5 字符数组。指针只是指向内存中的一个位置。数组声明一块内存并指向它。再次我不确定,所以我完全承认我可能错了或误解了什么。
猜你喜欢
  • 2019-11-23
  • 2012-08-23
  • 2011-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-25
  • 1970-01-01
  • 2012-11-27
相关资源
最近更新 更多