相关疑难解决方法(0)

将32位偏移量添加到x86-64 ABI的指针时是否需要符号或零扩展?

简介:我正在查看汇编代码来指导我的优化,并在将int32添加到指针时看到许多符号或零扩展.

void Test(int *out, int offset)
{
    out[offset] = 1;
}
-------------------------------------
movslq  %esi, %rsi
movl    $1, (%rdi,%rsi,4)
ret
Run Code Online (Sandbox Code Playgroud)

起初,我认为我的编译器在添加32位到64位整数时遇到了挑战,但我已经用Intel ICC 11,ICC 14和GCC 5.3证实了这种行为.

这个帖子证实了我的发现,但不清楚是否需要符号或零扩展.仅当尚未设置高32位时,才需要此符号/零扩展.但x86-64 ABI难道不够聪明吗?

我有点不愿意将所有指针偏移更改为ssize_t,因为寄存器溢出会增加代码的缓存占用空间.

assembly x86-64 abi compiler-optimization sign-extension

16
推荐指数
1
解决办法
2591
查看次数

为什么有数组的调用约定?

我正在阅读System V应用程序二进制接口,有一部分是我无法理解的.

首先,该文件指出

没有尝试为C以外的语言指定ABI

(第10页).

稍后,在第20页,数组分为MEMORY,POINTER等:

聚合(结构和数组)和联合类型的分类如下:
...

然后使用分类来定义调用约定 - 它们的值和边界如何传递给函数并从函数返回.如果我正确读取算法,则可以将数组分类为INTEGER,MEMORY或SSE.

但是在C语言中,数组总是作为指针传递和返回.那么为什么对数组进行分类以及在哪种情况下数组类很重要呢?

c arrays x86-64 calling-convention

5
推荐指数
1
解决办法
109
查看次数

从编译器的角度来看,如何处理数组的引用,以及为什么不允许传递值(不是衰减)?

我们知道,在C++中,我们可以将数组的引用作为参数传递f(int (&[N]).是的,它是iso标准保证的语法,但我很好奇编译器如何在这里工作.我找到了这个帖子,但遗憾的是,这并没有回答我的问题 - 编译器如何实现这种语法?

然后我写了一个演示,希望从汇编语言中看到一些东西:

void foo_p(int*arr) {}
void foo_r(int(&arr)[3]) {}
template<int length>
void foo_t(int(&arr)[length]) {}
int main(int argc, char** argv)
{
    int arr[] = {1, 2, 3};
    foo_p(arr);
    foo_r(arr);
    foo_t(arr);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

最初,我它仍会衰减到指针,但会通过寄存器隐式传递长度,然后转回函数体中的数组.但汇编代码告诉我这不是真的

void foo_t<3>(int (&) [3]):
  push rbp #4.31
  mov rbp, rsp #4.31
  sub rsp, 16 #4.31
  mov QWORD PTR [-16+rbp], rdi #4.31
  leave #4.32
  ret #4.32

foo_p(int*):
  push rbp #1.21
  mov rbp, rsp #1.21
  sub rsp, 16 #1.21
  mov QWORD …
Run Code Online (Sandbox Code Playgroud)

c++ arrays compiler-construction assembly pointers

4
推荐指数
1
解决办法
202
查看次数