在纯装配中输出整数的更有效方法

时间:2010-11-07 11:04:40

标签: compiler-construction performance x86-64 nasm

我正在寻找使用纯汇编输出整数。我在64位Linux机器上使用nasm。目前我正在寻找一种输出整数来调试编译器的方法,但我想使用相同的代码来编写操作系统,这也是我不仅仅使用printf()的原因。经过多次搜索和挫折,我想出了这段代码

    SECTION .data
var:    db  "      ",10,0

    SECTION .text
global main
global _printc
global _printi

main:
    mov rax, 90
    push    rax
    call    _printi

    xor rbx, rbx
    mov rax, 1
    int 0x80

_printi:
    pushf
    push    rax
    push    rbx
    push    rcx
    push    rdx

    mov rax, [rsp+48]
    mov rcx, 4
.start:
    dec rcx
    xor rdx, rdx
    mov rbx, 10
    div rbx
    add rdx, 48
    mov [var+rcx], dl
    cmp rax, 0
    jne .start

    mov rax, [var]
    push    rax
    call    _printc
    pop rax

    pop rdx
    pop rcx
    pop rbx
    pop rax
    popf
    ret

_printc:
    push    rax
    push    rbx
    push    rcx
    push    rdx

    mov rax, [rsp+40]
    mov [var], rax
    mov rax, 4
    mov rbx, 1
    mov rcx, var
    mov rdx, 4
    int 0x80

    pop rdx
    pop rcx
    pop rbx
    pop rax
    ret

请注意,在移植到OS开发时,我将使用BIOS调用替换0x80调用。

我的问题是如何进一步优化甚至美化这段代码。我的第一个想法是单独替换所有寄存器,但没有任何64位pusha指令......

1 个答案:

答案 0 :(得分:2)

以下是对例程的一些可能的更改:

_printi:
    pushf
    push    rax
    push    rbx
    push    rcx
    push    rdx

    mov rax, [rsp+48]
    mov rcx, 4
    mov rbx, 10 ; --moved outside the loop
.start:
    dec rcx
    xor rdx, rdx
    div rbx
    add rdx, 48
    mov [var+rcx], dl
    cmp rax, 0
    jne .start

    ; mov rax, [var] -- not used
    ; push    rax -- not used
    call    _printc
    ; pop rax -- not used

    pop rdx
    pop rcx
    pop rbx
    pop rax
    popf
    ret

我还注意到算法中的一些限制。如果该数字大于9999,则代码将继续将数字放在分配的空间之外,覆盖其他一些数据。该例程不是完全可重复使用的,即如果你打印123,那么它将是129。