Типичный пример, который преподаватели любят задавать начинающим изучать ассемблер – написать программу преобразующую двоичное число находящееся, например в регистре EAX в строку символов и вывести ее на экран или в файл. Ниже показаны два варианта такой программы, использующей условные переходы: Код (Text): 1) mov ecx,8; количество цифр в строке mov edi,offset String; адрес строки в edi @@: rol eax,4; преобразуемое число в регистре eax push eax cmp al,9;если al < 10, CF = 1 ja a1 add al,'0' jmp short a2 a1: add al,'7' a2: stosb; помещаем значение из AL в строку pop eax loop @b; уменьшаем счетчик ---------------------------------------------------- 2) add al,'0' cmp al,'9'; если al < 10, CF = 1 jbe a1 add al,7 a1: stosb; помещаем значение из AL в строку Для увеличения скорости выполнения программы, стараются как можно реже использовать условные переходы. Та же самая задача при использовании команд DAS и DAA может быть выполнена следующим образом: Код (Text): 3) mov edi,offset String; адрес строки в edi mov ecx,4 @@: rol eax,8 push eax push eax shr al,4; работаем со старшей тетрадой call Hex2 pop eax and al,0Fh; обнуляем старшую тетраду call Hex2; работаем с младшей тетрадой pop eax loop @b ... Hex2: add al,90h ;если в al была цифра 0..9, тогда в al ;будет 90h..99h, если в al была цифра 0Ah..0Fh, ;тогда в al будет 9Ah..9Fh daa ; 0-9: 90h..99h CF=0 ; A-F: 00h..05h CF=1 adc al,40h ; 0-9: D0h..D9h ; A-F: 41h..46h daa ; 0-9: 30h..39h ; A-F: 41h..46h stosb ; помещаем значение из AL в строку ret ----------------------------------------------------- 4) cmp al,10 ; если al < 10, CF = 1 sbb al,69h;если в al была цифра 0..9, тогда в al ;будет 96h..9Fh, если в al была цифра 0Ah..0Fh, ;тогда в al будет 0A1h..0A6h das ; 0-9: 96h..9Fh минус 66h -> 30h..39h, ; A-F: 0A1h..0A6h минус 60h -> 41h..46h stosb ; помещаем значение из AL в строку ------------------------------------------------------- 5) and al,0Fh; обнуляем старшую тетраду cmp al,10; если al < 10, CF = 1 sbb ah,ah; если al < 10, то ah=0, иначе ah=0FFh and ah,1; сбрасываем CF, ah = ah&1 (в ah окажется 0 или 1) daa; если в al было 0..9, тогда содержимое al не изменится add al,'1'; если в al было A..F тогда в al стало 10h..15h sub al,ah stosb; помещаем значение из AL в строку ------------------------------------------------------- 6) and eax,0Fh; обнуляем старшую тетраду cmp al,10; если al < 10, CF = 1 adc ah,0; если al < 10, то ah=1, иначе ah=0 daa; если в al было 0..9, тогда содержимое al не изменится add al,'1'; если в al было A..F тогда в al стало 10h..15h sub al,ah stosb; помещаем значение из AL в строку --------------------------------------------------------- 7) and eax,0Fh; обнуляем старшую тетраду cmp al,10; если al < 10, CF = 1 sbb ebx,ebx; если al < 10, то ebx=-1, иначе ebx=0 and ebx,ebx; сброс CF и AF daa; если в al было 0..9, тогда содержимое al не изменится lea eax,[ebx+eax+31h];add al,'1'; если в al было A..F тогда в al стало 10h..15h stosb; помещаем значение из AL в строку ------------------------------------------------------------ 8) cmp al,10;если al < 10, CF = 1 sbb ebx,ebx; если al < 10, то ebx=0, иначе ebx=-1 CF=AF=1 daa ; если в al было A..F, тогда al равно 10h..15h and ebx,-103; если 0..9, тогда al равно 66h..6Fh lea eax,[eax+ebx+31h]; если A..F, тогда al равно 41h..46h stosb; помещаем значение из AL в строку ------------------------------------------------------------- 9) and al,0Fh; обнуляем старшую тетраду cmp al,10;если al < 10, CF = 1 sbb ebx,ebx; если СF=0, то ebx=0, иначе ebx=-1 and ebx,-13; сбрасываем CF и AF, в ebx окажется 0 или -13 das; если 0..9, тогда al не изменится lea eax,[eax+ebx+3Dh]; если A..F, тогда al равно 3..9 stosb; помещаем значение из AL в строку ---------------------------------------------------------- 10) and al,0Fh; обнуляем старшую тетраду cmp al,10; если al < 10, CF = 1 sbb ebx,ebx; если СF=0, то ebx=0, иначе ebx=-1 CF=AF=1 das; если 0..9, тогда al не изменится and ebx,-167; если A..F, тогда al равно 3..9 lea eax,[eax+ebx+3Dh] stosb; помещаем значение из AL в строку Вариант с использованием команды XLAT, где-то в сегменте данных должна быть таблица перекодировки: table db '0123456789ABCDEF' Код (Text): and al,0Fh; обнуляем старшую тетраду xlat stosb; помещаем значение из AL в строку Вариант с использованием команды условной пересылки CMOVcc: Код (Text): mov ecx,8; количество цифр в строке mov edi,offset String; адрес строки в edi mov bl,30h @@: rol eax,4 push eax; преобразуемое число в регистре eax and al,0Fh; обнуляем старшую тетраду mov dl,37h cmp al,10 cmovb edx,ebx add al,dl stosb; помещаем значение из AL в строку pop eax shr eax,4; переходим к следующей тетраде loop @b; уменьшаем счетчик Вариант без использования условного ветвления: Код (Text): and al,0Fh; обнуляем старшую тетраду cmp al,10 sbb ebx,ebx; если СF=0, то ebx= 0, иначе ebx=-1 and ebx,-7; в ebx окажется 0 или -7 lea eax,[eax+ebx+37h] stosb; помещаем значение из AL в строку
Предлагаю закрепить эту тему Ну или вынести маленькой отдельной статьей. Ведь алгоритмы действительно интересные и полезные, и искать их потом по форуму будет проблематично.
В догонку Код (Text): 11) and al,0Fh cmp al,10 cmc ; если al < 10, CF = 0 adc al,30h;если в al была цифра 0..9, тогда в al ;будет 30h..39h, если в al была цифра 0Ah..0Fh, тогда в al будет 3Bh..40h daa ; 0-9: 30h..39h, ; A-F: 3Bh..40h плюс 6 -> 41h..46h stosb ; помещаем значение из AL в строку
Да, тема древняя, но найти сходу симпатичные варианты не так просто - вот с трудом отыскал вариант Black_mirror'a
Для разнообразия можно задействовать MMX Код (Text): x dd 0FACD123h mask dq 0F0F0F0F0F0F0F0Fh ascii dq 3030303030303030h hex dq 3939393939393939h ascii2 dq 0707070707070707h s rb 9 --//-- pxor mm0,mm0 punpcklbw mm0,qword[x] movq mm1,mm0 psrlw mm1,12 por mm0,mm1 pand mm0,[mask] paddusb mm0,[ascii] movq mm1,[hex] pcmpgtb mm1,mm0 pandn mm1,[ascii2] paddusb mm0,mm1 pshufw mm0,mm0,00011011b movq qword[s],mm0
тогда лучше загрузить mask, ascii, hex и ascii2 в свободные регистры mmx и использовать это на очень длинных начальных данных.
"Продолжаем разговор" (©"Малыш и Карлсон, который живет на крыше") Код (Text): 12) and al,0Fh; обнуляем старшую тетраду daa ;F->15h 1->1 add al,0F0h;F0+15h->05h CF=1 F0+1->F1 CF=0 adc al,40h ;46h 31h stosb; помещаем значение из AL в строку 12) and al,0Fh; обнуляем старшую тетраду daa ; F->15h 1->1 add al,70h; 70h+15h->85h SF=1 70h+1->71h SF=0 cbw ; ah=0FFh ah=0 sub al,ah ; 85+1->86h 71h sub al,40h; 46h 31h stosb; помещаем значение из AL в строку 13) and al,0Fh; обнуляем старшую тетраду sub al,11h; F->FEh 1->F0h db 0D4h,0F9h;FE->0105h F0->00F0h add al,41h ;05+41->46h F0+41->31h stosb; помещаем значение из AL в строку 14) and al,0Fh; обнуляем старшую тетраду aam; 0F->105h 01->0001 db 0D5h,11h; 105h->16h 0001->01 add al,30h ;16+30->46h 01+30->31h stosb; помещаем значение из AL в строку 15) and ax,0Fh; обнуляем старшую тетраду aaa; 0F->105h 01->0001 db 0D5h,11h; 105h->16h 0001->01 add al,30h ;16+30->46h 01+30->31h stosb; помещаем значение из AL в строку
По поводу строки вы сказали слишком мало - стока представлеяет собой десятичное или хекс инвариант ?? надо по форуму поискать rain вроде поднимал подобную тему ...