【问题标题】:_IO_puts and Dynamic Instruction count_IO_puts 和动态指令计数
【发布时间】:2021-10-31 21:26:42
【问题描述】:

我是汇编新手,有一个简单的 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 处理器上字符串长度的增加而变化,有时还会减少?

【问题讨论】:

  • 你需要深入挖掘,大概是_IO_sputn。它可能正在循环您的字符串。 stdout 是行缓冲的,因此它首先存储您的字符串,并且仅当\nputc 添加时才输出它。这涉及到一个memcpy,它会随着你的字符串的长度而缩放。
  • 它也在做strlen(str)...
  • 哈哈是的好点:D
  • glibc strlen 在 MIPS 上使用纯 C bithack 一次检查 4 个字节。 (与大多数其他具有手写 asm 的 ISA 不同)。 Why does glibc's strlen need to be so complicated to run quickly?。这很不简单,但它的启动策略取决于一致性。

标签: c assembly mips


【解决方案1】:

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

MIPS 上的 glibc strlen 使用纯 C bithack 一次检查 4 个字节。 (与大多数其他具有手写 asm 的 ISA 不同)。 Why does glibc's strlen need to be so complicated to run quickly?。这很不简单,它的启动策略取决于字符串开头的对齐方式。

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


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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    相关资源
    最近更新 更多