Blog. Just Blog

Вывод QWORD в виде десятичного числа

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Для преобразования и форматированного вывода 32-битных значений в ассемблере используется стандартная API-функция wsprintf, но она бесполезна при работе с большими числами, например QWORD (64 бита). Значит обойдемся совсем без использования API.
  1. ;---------------------------------------------------
  2. ; Преобразование QWORD в десятичное число
  3. ; Параметры вызова:
  4. ; dwHigh - Старшее двойное слово
  5. ; dwLow  - Младшее двойное слово
  6. ; lpBuff - указатель на буфер-приемник
  7. ;---------------------------------------------------
  8. proc    bignum dwHigh:DWORD, dwLow:DWORD, lpBuff:DWORD
  9.         pushad                   ; Сохранить все регистры
  10.         mov     eax,[dwLow]      ; Младшее двойное слово
  11.         mov     edx,[dwHigh]     ; Старшее двойное слово
  12.         mov     edi,[lpBuff]     ; Указатель на буфер-приемник
  13.  
  14.         xchg    esi,edx          ; Сохранить старший dword
  15.         mov     ebx,10           ; Основание системы счисления
  16.         xor     ecx,ecx          ; Счетчик десятичных цифр
  17. .bignum_1:
  18.         xchg    eax,esi          ; Расчитать десятичную цифру
  19.         xor     edx,edx
  20.         div     ebx
  21.         xchg    esi,eax
  22.         div     ebx
  23.         or      dl,'0'           ; Преобразовать результат в символ цифры
  24.         push    edx              ; Сохранить цифру в стеке
  25.         inc     ecx              ; Увеличить счетчик цифр
  26.         or      eax,eax          ; Все преобразовали?
  27.         jnz     .bignum_1
  28.  
  29. .bignum_2:
  30.         pop     eax              ; Записать все цифры из стека в буфер
  31.         stosb
  32.         loop    .bignum_2
  33.         xor     eax,eax          ; Признак окончания строки
  34.         stosb
  35.         popad                    ; Восстановить все регистры
  36.         ret                      ; Ворзврат из процедуры
  37. endp
Пример использования:
  1. ; Сегмент данных
  2. section '.data' data readable writeable
  3. ...
  4. buff rb 100h
  5.  
  6. ; Сегмент кода
  7. section '.code' code readable executable
  8. ...
  9.         mov     edx,70655326h  ; EDX:EAX = 7065532612345678h
  10.         mov     eax,12345678h  ; в десятичной системе это 8098970927874987640
  11.         stdcall bignum, edx, eax, buff
  12.         ; После выполнения буфер содержит строку "8098970927874987640"
Функция получилась достаточно универсальной. Для преобразования числа в другую систему счисления с основанием, отличным от 10, достаточно изменить в коде функции mov ebx,10 на нужное значение. Или, как вариант, ввести дополнительный параметр вызова функции, определяющий основание.

Поделиться ссылкой ВКонтакте
Просмотров: 9911 | Комментариев: 4

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Yoshida (17.04.2012 в 17:11):
Понадобилось выводить шестнадцатеричное число на экран, немного доработал bignum:


;---------------------------------------------------
; Преобразование QWORD в десятичное число
; Параметры вызова:
; dwHigh - Старшее двойное слово
; dwLow  - Младшее двойное слово
; lpBuff - указатель на буфер-приемник
;---------------------------------------------------
proc    bignumhex dwHigh:DWORD, dwLow:DWORD, lpBuff:DWORD
        pushad                   ; Сохранить все регистры
        mov     eax,[dwLow]      ; Младшее двойное слово
        mov     edx,[dwHigh]     ; Старшее двойное слово
        mov     edi,[lpBuff]     ; Указатель на буфер-приемник
 
        xchg    esi,edx          ; Сохранить старший dword
        mov     ebx,16           ; Основание системы счисления
        xor     ecx,ecx          ; Счетчик десятичных цифр
.bignum_1:
        xchg    eax,esi          ; Расчитать десятичную цифру
        xor     edx,edx
        div     ebx
        xchg    esi,eax
        div     ebx
        cmp    dl,9
        jbe    .num
        add    dl,'A'-10
        jmp    .next
     .num:
        or      dl,'0'           ; Преобразовать результат в символ цифры
     .next:
        push    edx              ; Сохранить цифру в стеке
        inc     ecx              ; Увеличить счетчик цифр
        or      eax,eax          ; Все преобразовали?
        jnz     .bignum_1
 
.bignum_2:
        pop     eax              ; Записать все цифры из стека в буфер
        stosb
        loop    .bignum_2
        xor     eax,eax          ; Признак окончания строки
        stosb
        popad                    ; Восстановить все регистры
        ret                      ; Ворзврат из процедуры
endp
Predator (24.04.2009 в 19:26):
Отличный алгоритм, я вчера написал подобную функцию, но с меньшими возможностями: перевод числа возможен, если оно не превышает DWORD. Принцип такой: EAX = делимое; EBX = делитель = 1000000000; ESI = куда сохранять преобразованное число.

@@:    Делимое делится на 1000000000, частное преобразовывается к ASCII и сохраняется, далее делитель(EBX) уменьшается на ноль и остаток(EDX) копируется в EAX, JMP @B.
    Я конечно не много пропустил, что и так понятно: увеличение на байт значения куда сохраняется число(если это не стек), и проверка остатка если EDX < 0Ah то на выход и там сохраняем последнее число.

    Ни как не могу найти в сети подобных алгоритмов. (Если возможно подскажите где можно найти.)
ManHunter (17.01.2009 в 12:56):
Да, действительно, лишний код остался после оптимизации. Поправил, спасибо.
Zummenix (17.01.2009 в 12:43):
Мне не понятно зачем в коде:
mov   edi,buff
Если мы при вызове функции пишем:
stdcall bignum, edx, eax, buff

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.52 сек. / MySQL: 2 (0.028 сек.) / Память: 4.5 Mb
Наверх