Blog. Just Blog

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

Версия для печати Добавить в Избранное Отправить на E-Mail 05.10.2008 | Категория: Образ мышления: 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 на нужное значение. Или, как вариант, ввести дополнительный параметр вызова функции, определяющий основание.

Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на Я.ру Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Поделиться ссылкой на Friendfeed Добавить в Яндекс.Закладки Добавить в закладки Memori Добавить в закладки Google
Просмотров: 2719 | Комментариев: 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-2012
При использовании материалов ссылка на сайт обязательна
Время генерации: 0,19 сек. / MySQL: 2 (0,001 сек.) / Память: 3,5 Mb
Наверх