首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >尽快将程序集(64位,NASM)中的整数转换为字符串

尽快将程序集(64位,NASM)中的整数转换为字符串
EN

Stack Overflow用户
提问于 2021-02-18 23:46:21
回答 1查看 849关注 0票数 1

我用64位NASM编写了一个printint函数,它将一个整数打印到STDOUT。但是,它确实很慢,在进行了一些基准测试之后,我确定将整数转换为字符串是目前为止最慢的部分。

我当前将ints转换为字符串的策略如下所示:

如果数字为0,则跳到特例。如果数字为负数,则打印负号,将其转换为正整数,continue

  • Create为10字节缓冲区(足以容纳所有32位整数)和指向缓冲区

  • 后面的指针,检查该数字是否为0;如果是的话,我们就完成了。

  • 将数字除以10,将剩余的转换为ASCII

  • ,将剩余的放入缓冲区(从返回到缓冲区指针

  • 循环返回到步骤4

)。

我试着用谷歌搜索别人是怎么做的,这和我做的差不多,除以10,直到这个数字是0。

以下是相关代码:

代码语言:javascript
运行
复制
printint:                       ; num in edi
    push rbp                    ; save base pointer
    mov rbp, rsp                ; place base pointer on stack
    sub rsp, 20                 ; align stack to keep 20 bytes for buffering
    cmp edi, 0                  ; compare num to 0
    je _printint_zero           ; 0 is special case
    cmp edi, 0
    jg _printint_pos            ; don't print negative sign if positive

    ; print a negative sign (code not relevant)
    xor edi, -1                 ; convert into positive integer
    add edi, 1
_printint_pos:
    mov rbx, rsp                ; set rbx to point to the end of the buffer
    add rbx, 17
    mov qword [rsp+8], 0        ; clear the buffer
    mov word [rsp+16], 0        ; 10 bytes from [8,18)
_printint_loop:
    cmp edi, 0                  ; compare edi to 0
    je _printint_done           ; if edi == 0 then we are done
    xor edx, edx                ; prepare eax and edx for division
    mov eax, edi
    mov ecx, 10
    div ecx                     ; divide and remainder by 10
    mov edi, eax                ; move quotient back to edi
    add dl, 48                  ; convert remainder to ascii
    mov byte [rbx], dl          ; move remainder to buffer
    dec rbx                     ; shift 1 position to the left in buffer
    jmp _printint_loop
_printint_done:
    ; print the buffer (code not relevant)
    mov rsp, rbp                ; restore stack and base pointers
    pop rbp
    ret

我如何优化它,使它能够运行得更快?或者,是否有更好的方法将整数转换为字符串?

我不想在C标准库中使用printf或任何其他函数。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-20 00:43:58

原来我搞错了瓶颈的源头。我的基准有缺陷。虽然微优化(如幻数乘法和更好的循环)确实有帮助,但最大的瓶颈是系统。

通过使用缓冲读写(缓冲区大小为16 kB),我能够实现我的目标,读取和打印整数比扫描和打印速度快。

创建一个输出缓冲区将一个特定的基准加速了4倍以上,而微优化则使其速度提高了大约25%。

对于将来偶然发现这篇文章的人来说,下面是我所做的优化:

  1. 将所有sys_write调用替换为write_buf调用,其中write_buf将输出写入缓冲区,并仅在缓冲区满时打印缓冲区。这样一个reader.
  2. Replaced函数的实现是留给iteration.
  3. Changed的一个练习--幻数乘法除法,它节省了每个循环iteration.
  4. Changed的几个时钟周期,而循环成了do...while循环,每个循环迭代保存了一个jmp指令(在time).
  5. Optimizing单独的指令上加了相当多的部分)(例如使用neg而不是xor,add),并删除多余的指令。

我可以做的另一个可能的改进(但没有)是除以更大的基础和使用查找表,在注释中提到了phuclv。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66269798

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档