c - _IO_puts 和动态指令计数

标签 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;
}

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

最佳答案

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

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

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


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

关于c - _IO_puts 和动态指令计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69029646/

相关文章:

c - 结构中的位是否有保证

C 到 MIPS - 指令引用未定义 QTSpim

c - STM32F407 USART1 : Clearing USART_FLAG_TC requires pgm to be halted before actually clearing the bit

c++ - 在SoupSession中更改libsoup身份验证

c - 使用 "int 0x80"调用 Linux 内核系统调用

来自 NASM 代码的 Linux64 线程本地存储 (TLS) 数据

java - 调用 JNI_CreateJavaVM 使程序崩溃

c - 在 C 中声明结构

c++ - 如果静态和动态加载 libcrypto,则动态/共享库加载两次/RSA_check_key 失败

C 中的调用堆栈回溯