В своё время в практике разработчика довольно часто можно было встретить задачи по преобразованию типов данных, одним из подвидов которых является конвертация шестнадцатеричного числа в строку, иными словами преобразование байта/слова/двойного слова в строку символов ASCIIZ (упрощенно: текстовое представление) для последующего использования. Проблема стара как мир ЭВМ и на низком уровне состоит в последовательной конвертации полубайтов (ниббла, 4 бит) в представление ASCIIZ. Чаще всего полученное представление числа используется для вывода на устройство отображения (экран). И все было бы достаточно тривиально, если бы между шестнадцатеричными значениями (0..F) и соответствующими кодами таблицы (набора) ASCII имелось прямое соответствие, но разработчики стандарта решили иначе, итогом чего явился досадный факт разделения ряда ASCII-кодов символов на границе '9' и 'A' (шестнадцатеричные значения 39h и 41h соответственно). Существующая реальность имеет два независимых ряда: 0-9 и A-F, и именно по этой вот несуразной причине алгоритмы конвертации несколько усложнились.
16-битный код
Если брать старые-добрые времена, то там что называется "под реальным железом" для конвертации шестнадцатеричного числа в строку не было никаких доступных разработчику готовых сервисных функций ни в BIOS, ни в DOS. Поэтому давно ушедшее время 80-90х годов было чрезвычайно богато на различного рода реализации преобразования шестнадцатеричного числа в строку. Самый компактный из полученных мною в своё время алгоритмов был длиною всего 19 байт и представлял следующее:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ;----------------------------------------------------------------------------- ; Функция преобразования слова в ASCII представление		 ; вход:  AX = слово для конвертации, ES:DI = смещение буфера, флаг направления (DF) сброшен. ; выход: ES:DI = строка в формате ASCII (4 байта) ; Прим.: Не сохраняет регистры AX/CX/DI ;----------------------------------------------------------------------------- str_word_to_ascii: 	mov	cx, 4		; в слове 4 ниббла (полубайта) @@: 	rol	ax, 4		; выдвигаем младшие 4 бита 	push	ax		; сохраним AX 	and	al, 0Fh		; оставляем 4 младших бита AL 	cmp	al, 0Ah		; сравниваем AL со значение 10 	sbb	al, 69h		; целочисленное вычитание с заёмом 	das			; BCD-коррекция после вычитания 	stosb                   ; помещаем получившийся символ в буфер 	pop	ax		; восстановим AX 	loop	@b		; цикл 	ret		 | 
За основу функции взят некий алгоритм Эллисона (Allison's Algorithm), который бесспорно гениален, но совершенно не интуитивен, поскольку в нем используется довольно редко применяемая на практике, а главное достаточно непростая в логике, инструкция das.
Пояснение к алгоритму функции:
- производим обнуление старших четырех битов регистра AL, поскольку будем работать с младшими четырьмя;
- получившееся значение в регистре ALсравнивается с 0Ah (10): если значение регистра меньше, то выставляется флаг переноса (CF), если больше, то флаг сбрасывается;
- инструкция sbb производит "целочисленное вычитание с заёмом" из регистра ALзначения 69h, учитывая при этом (изменившееся ранее) значение флага переноса;
- инструкция das выполняет "десятичную коррекцию после вычитания". Предназначается для исполнения сразу после команд sub/sbb и выполняет коррекцию результата вычитания (разности) двух упакованных двоично-десятичных чисел (BCD). Корректирует содержимое регистра ALтак, что бы в результате выполнения получилось двухзначное упакованное двоично-десятичное число.
Вот именно описанная выше логика у нас и обыгрывает разрыв в таблице ASCII и обеспечивает преобразование двух шестнадцатеричных рядов (0-9 и A-F) в коды соответствующих символов в таблице ASCII. При вызове функции подразумевается, что флаг направления (DF) выставлен в 0, то есть задано направление "вперед" (для более универсального кода можно в начале функции дописать команду cld).
32-битный код
Под Windows все прозаичнее, ведь под рукой у нас целая "продвинутая" операционная система, глупо было бы не добавить в неё несколько сотен функций :), поэтому тут у нас два пути решения задачи: использовать встроенные системные функции Win32 API либо писать собственную реализацию по преобразованию шестнадцатеричного значения в строку ASCII.
Системные функции
Самая простая идея под Windows состоит в использовании системной функции-форматера под названием wsprintf. Функция wsprintf представляет собой мощнейший системный преобразователь форматов, который создает результирующую строку из значений входных параметров, модифицируя их тип/длину в соответствии с задаваемым специальными спефицикаторами шаблоном вывода. Говоря простым языком, функция берет входные значения, конвертирует их (в соответствии с заданными требованиями) и помещает в выходной буфер. Типичный пример использования:
| 1 2 3 | . . . 	invoke	wsprintf,szValue,szFmt,eax . . . | 
где:
- EAXзадает число для конвертации;
- szValue определяет выходной буфер для формирования результата, который описывается в секции данных следующим образом:
 1szValue db 8 dup (0)
- а szFmt задает формат, к которому приводится входное значение. Тут ключевым моментом является спецификатор формата, который в случае преобразования в шестнадцатеричное текстовое представление выглядит как %08X, где число 8 задает разрядность получаемого результата, а X определяет шестнадцатеричное представление. Описывается в секции данных следующим образом:
 1szFmt db '%08X',0
После отработки функции wsprintf в выходном буфере (szValue) образуется строка символов с текстовым представлением шестнадцатеричного числа. Только не забудьте в своем проекте импортировать функцию wsprintf из библиотеки USER32.DLL.
Собственная реализация
Если уж совсем хочется пользоваться собственным кодом, либо время исполнения функции критично, то можно воспользоваться и собственным решением. Оно мало чем отличается от своего 16-битного собрата, единственное что преобразована для работы с двойными словами и оптимизировано под соглашение о вызовах stdcall:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ;----------------------------------------------------------------------------- ; Функция преобразования двойного слова в ASCII представление		 ; Прим.: Не сохраняет регистры EAX/ECX/EDI ;----------------------------------------------------------------------------- proc	str_dword_to_ascii hexValue:DWORD, oBuffer:DWORD 	mov	eax, [hexValue]	; EAX = двойное слово для конвертации 	mov	edi, [oBuffer]	; EDI = выходной буфер 	mov	ecx, 8		; в двойном слове 8 нибблов (полубайт) @@: 	rol	eax, 4		; выдвигаем младшие 4 бита 	push	eax		; сохраним EAX 	and	al, 0Fh		; оставляем 4 младших бита AL 	cmp	al, 0Ah		; сравниваем AL со значение 10 	sbb	al, 69h		; целочисленное вычитание с заёмом 	das			; BCD-коррекция после вычитания 	stosb                   ; помещаем получившийся символ в буфер 	pop	eax		; восстановим EAX 	loop	@b		; цикл 	ret		 | 

А как преобразовать байт в шестнадцатеричное представление?
то же самое, только с одним байтом?
Огромное СПАСИБИЩЕ !
да не за чтоЩЕ, заходите еЩЕ! :)
Я в своё время для преобразования AX делал рекурсивный вариант
xchg ah,dl
call L0
xchg ax,dx
L0:
;Далее недокументированная команда процессора aam 10h
aam
org $-1
db 10h
call L1
xchg ah,al
L1:
add al,30h
jle L2
add al,7
L2:
ret
Кусок весь
L1:
add al,30h
jle L2
add al,7
L2:
В принципе можно заменить одной командой
xlat она же xlatb
только в bx указатель на таблицу положить
А можно пояснить, как проверяются границы введенных символов (буква-цифра) здесь:
add dl,09Fh
sub dl,01Ah
jb nextsym
add al,0BFh
sub al,01Ah
jae nextsym+n
команды add/sub воздействуют на флаг CF, команда jb выполняет переход в зависимости от значения флага CF. собственно на этом и построена логика. таким вот хитрым образом, видимо, проверяется попадание в заданный диапазон (цифра/буква) в таблице ASCII.