_IO_puts 和动态指令计数

_IO_puts and Dynamic Instruction count

我是汇编新手,有一个简单的 C 程序将字符串打印到标准输出。在汇编中,这转化为 main 调用 _IO_Puts_IO_puts 的实现如下摘自:https://code.woboq.org/userspace/glibc/libio/ioputs.c.html 如下所示。

int
_IO_puts (const char *str)
{
  int result = EOF;
  size_t len = strlen (str);
  _IO_acquire_lock (stdout);
  if ((_IO_vtable_offset (stdout) != 0
       || _IO_fwide (stdout, -1) == -1)
      && _IO_sputn (stdout, str, len) == len
      && _IO_putc_unlocked ('\n', stdout) != EOF)
    result = MIN (INT_MAX, len + 1);
  _IO_release_lock (stdout);
  return result;
}

我无法弄清楚为什么在模拟 MIPS 处理器上动态指令的数量会随着字符串长度的增加而变化,有时甚至会减少?

如评论中所述,glibc _IO_sputn 涉及执行 strlen 和该大小的 memcpy。

MIPS 上的 glibc strlen 使用一次检查 4 个字节的纯 C bithack。 (与大多数其他具有手写 asm 的 ISA 不同)。 。它非常不简单,它的启动策略取决于字符串开头的对齐方式。

这里更相关,在一个字的第 4 个字节找到终止 0 字节而不是下一个字的第一个字节可能也需要更少的指令。 (或者对于 MIPS64,第 8 名与第 1 名)。所以这可能就是您看到动态指令计数的非单调缩放的原因。


memcpy 对于 4(或 8)字节的倍数也将采用更少的指令,并且它通过在大小上分支以及可能对齐 src 和 dst 来选择策略。 (MIPS32/64r6 之前的 MIPS 不保证有效的未对齐存储)。因此,对不涉及刷新缓冲区的 stdio 函数的顺序调用可能导致 stdout 缓冲区的不同目标对齐方式。