Вывод QWORD в виде десятичного числа
Для преобразования и форматированного вывода 32-битных значений в ассемблере используется стандартная API-функция wsprintf, но она бесполезна при работе с большими числами, например QWORD (64 бита). Значит обойдемся совсем без использования API.Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------------
- ; Преобразование QWORD в десятичное число
- ; Параметры вызова:
- ; dwHigh - Старшее двойное слово
- ; dwLow - Младшее двойное слово
- ; lpBuff - указатель на буфер-приемник
- ;---------------------------------------------------
- proc bignum dwHigh:DWORD, dwLow:DWORD, lpBuff:DWORD
- pushad ; Сохранить все регистры
- mov eax,[dwLow] ; Младшее двойное слово
- mov edx,[dwHigh] ; Старшее двойное слово
- mov edi,[lpBuff] ; Указатель на буфер-приемник
- xchg esi,edx ; Сохранить старший dword
- mov ebx,10 ; Основание системы счисления
- xor ecx,ecx ; Счетчик десятичных цифр
- .bignum_1:
- xchg eax,esi ; Расчитать десятичную цифру
- xor edx,edx
- div ebx
- xchg esi,eax
- div ebx
- or dl,'0' ; Преобразовать результат в символ цифры
- 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
Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- ...
- buff rb 100h
- ; Сегмент кода
- section '.code' code readable executable
- ...
- mov edx,70655326h ; EDX:EAX = 7065532612345678h
- mov eax,12345678h ; в десятичной системе это 8098970927874987640
- stdcall bignum, edx, eax, buff
- ; После выполнения буфер содержит строку "8098970927874987640"
Просмотров: 10054 | Комментариев: 4
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Predator
(24.04.2009 в 19:26):
Отличный алгоритм, я вчера написал подобную функцию, но с меньшими возможностями: перевод числа возможен, если оно не превышает DWORD. Принцип такой: EAX = делимое; EBX = делитель = 1000000000; ESI = куда сохранять преобразованное число.
@@: Делимое делится на 1000000000, частное преобразовывается к ASCII и сохраняется, далее делитель(EBX) уменьшается на ноль и остаток(EDX) копируется в EAX, JMP @B.
Я конечно не много пропустил, что и так понятно: увеличение на байт значения куда сохраняется число(если это не стек), и проверка остатка если EDX < 0Ah то на выход и там сохраняем последнее число.
Ни как не могу найти в сети подобных алгоритмов. (Если возможно подскажите где можно найти.)
@@: Делимое делится на 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
mov edi,buff
Если мы при вызове функции пишем:
stdcall bignum, edx, eax, buff
Добавить комментарий
Заполните форму для добавления комментария
;---------------------------------------------------
; Преобразование 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