Знаковое целое число из ASCII x86_64 с ассемблер макро


Я реализовал алгоритм, который преобразует целое число со знаком в эквивалентное ASCII-строку с соответствующим знаком в первый байт. Я испытывал его на нескольких чисел и он правильно работал. Но как новичок я бы не заметил некоторые логические ошибки или недостатки.

Я прошу любые идеи, как сделать это более эффективным и элегантным.

;;;;MACRO SECTION//////////////////////////////////////////////////////////////

%macro Int2ascii 2                  ;1 - number, 2 - string

    mov     r12, %2                 ;move ADDRESS of string

    mov     eax, dword[%1]
    cmp     eax, 0
    jge     %%placePlus             ;check either number is negative or positive

    %%placeMinus:
        mov     byte [r12], "-"     ;fill the first (0th) byte with the sign
        mov     rdi, -1             ;remember the sign
        ;neg     eax                ;negate number and forgot the sign (deprecated: see EDIT 1)
        jmp     %%skipPlacePlus 

    %%placePlus:
        mov     byte [r12], "+"
        mov     rdi, 1               ;remember the sign

    %%skipPlacePlus:

    xor     rcx, rcx                ;digit counter here (used implicitely in %%fillLoop)
    mov     ebx, 10 

    %%divideLoop:
        cdq                         ;eax -> edx:eax
        idiv    ebx                 ;signed division, reminder is also signed
        imul    rdx, rdi            ;"unsign" the current reminder
        ;div     ebx                ;(deprecated: see EDIT 1)
        push    rdx                 ;push the reminder to stack

        inc     rcx                 ;increment digit counter

        cmp     eax, 0
        jne     %%divideLoop

    mov     rdi, 1                  ;note that the first (0th) byte was number sign (+/-) 

    %%fillLoop:
        pop     rax                     ;pop back reminders

        add     al, "0"                 ;ascii code for digit
        mov     byte [r12 + rdi], al    ;fill string 
        inc     rdi 
        loop    %%fillLoop 

    mov     byte [r12 + rdi], 0x00      ;terminate string

%endmacro

Пример вывода

Как @TobySpeight предложил я проверил этот алгоритм на цифр: -1, 0, 1, 9, 10, 0x7fffffff, 0x80000000. Выход (gdb сессии):

(gdb) x/s &sNegOne
0x600377:   "-1"
(gdb) x/s &sZero
0x600368:   "+0"
(gdb) x/s &sPosOne
0x600386:   "+1"
(gdb) x/s &sNine
0x600395:   "+9"
(gdb) x/s &sTen
0x6003a4:   "+10"
(gdb) x/s &sNumber1
0x6003b3:   "+2147483647"
(gdb) x/s &sNumber2
0x6003c2:   "-2147483648"

Я уже понял, что пытается рассмотреть только положительные значения без знака приводит к двойное слово превышения действительной сначала дважды слово 0x80000000 но инвалид после взятия абсолютного значения 0x7fffffff + 1 который не подписан двойное слово. Я победил его подписали дивизии. Проблема здесь заключается в подписанных напоминания отдел также подписаны и не больше применимо для хранения цифрами и без дополнительной обработки, которая является просто умножением на -1 или 1 в зависимости от знака.



Комментарии