代码之家  ›  专栏  ›  技术社区  ›  Marco Lugo

计算机如何将ASCII字符串转换为有符号或无符号数字?

  •  0
  • Marco Lugo  · 技术社区  · 7 年前

    例如,如果我键入:

    -6

    通过什么机制转变成:

    1010

    它是基于硬件还是在内核中?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Peter Cordes    7 年前

    它是基于硬件还是在内核中?

    通常没有和没有。

    Linux等主流操作系统中的内核通常只会将字节的文本传递给用户空间。

    因此,用户空间程序获得一个字符串,即一个字符序列。(在简单情况下,例如UTF-8的ASCII子集,每个字符都是一个字节。)程序通常会使用以下函数: atoi() 将字符序列(代表数字的ASCII码)转换为二进制整数。这是一个标准的库函数,因为许多程序需要处理表示整数的字符串,但它和其他任何程序一样,是一个软件函数。

    一个简单的实现会有一个类似于

    int sum = 0;
    for (auto d: digits) {   // look at digits in MSB-first order
        sum = 10*sum + d;
    }
    // the first digit ends up being multiplied by 10 n times
    // the 2nd by 10 n-1 times, and so on. Each digit is multiplied by its place value.
    

    这个C++源代码将编译成多个asm指令来实现它。处理可选 - 通过求反也是一条单独的指令。通常有一个 neg 某种指令,或从零减去的方法,以获得2的补码逆。(假设2的补码硬件)。


    您可以通过使用更高级的指令来加快速度,这些指令在每个指令/每个时钟周期中做更多的工作。例如,在x86上,您可以使用几个SIMD指令将多位数的数字字符串转换为二进制整数,但这仍然只是使用乘法和加法指令。看见 How to implement atoi using SIMD? 为了更好地利用 pmaddwd 乘以位值向量并水平相加。而且 Fastest way to get IPv4 address from string 这是一个很酷的例子,说明了你可以用压缩比较和查找 pshufb

    函数,如 scanf("%d", &num) 将输入读取为数字的方法在用户空间中实现,但在后台它使用了一个系统调用,如 read() 获取数据。(如果C stdio输入缓冲区为空。)


    一些“玩具”/教学系统,如MARS和SPIM MIPS模拟器,具有获取或打印整数的系统调用(输入或结果为整数寄存器)。在这种情况下,是的,内核在软件中实现了这一点。

    或者根据实现的不同,实际上根本没有内核,而 syscall 指令转移到模拟器/模拟器的输入/输出功能,因此,从这个虚拟模拟机内运行的软件的角度来看,确实存在整数转换的硬件支持。但是没有真正的硬件能够在微码或实际硬件中完成全部工作,至少没有任何主流架构。