_IO_puts 和动态指令计数

Ano*_*alc 5 c assembly mips

我是汇编新手,有一个简单的 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;
}
Run Code Online (Sandbox Code Playgroud)

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

Pet*_*des 4

正如评论中所指出的,glibc_IO_sputn涉及执行该大小的 strlen 和 memcpy。

MIPS 上的 glibc strlen 使用纯 C bithack 一次检查 4 个字节。(与大多数其他具有手写汇编的 ISA 不同)。 为什么glibc的strlen需要这么复杂才能快速运行?。它非常不简单,它的启动策略取决于字符串开头的对齐方式。

0这里更相关的是,在一个字的第 4 个字节与下一个字的第 1 个字节查找终止字节可能也花费更少的指令。(或者 MIPS64 的第 8 与第 1)。因此,这可能就是您看到动态指令计数非单调缩放的原因。


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