OLD-idmessage-240547

#2042992
-sc-
Участник

Наконец-то появилось время (суббота 🙂 ) Если все еще актуально, вот работающая версия (под Windows).Компилировал [link url='http://wasm.ru/baixado.php?mode=tool&id=230'] Tasm32(5.3) [/link], отлаживал [link url='http://wasm.ru/baixado.php?mode=tool&id=89'] odbg(1.10) [/link]Скомпилировать проще всего так:1. Распаковать Tasm в какую-нибудь дир., например d:\bin\tasm2. В дир. Examples создать дир. duodec3. В дир. duodec создать файл duodec.asm с исходным кодом4. Тут же (в duodec) создать файл duodec.def5. B тут же создать файл make.batДля компиляции выполнить make.batПосле запуска программа выводит знак ‘?’. Дальше можно ввести 8-ричное число (цифры должны быть меньш 😎 После ввода числа нужно ввести пробел. Программа распечатает число в 12-рич. сис. счисл.Пример работы:D:\bin\tasm\EXAMPLE\duodec>duodec.exe? 0 = 0D:\bin\tasm\EXAMPLE\duodec>duodec.exe? 1 = 1D:\bin\tasm\EXAMPLE\duodec>duodec.exe? 7 = 7D:\bin\tasm\EXAMPLE\duodec>duodec.exe? input error: digit must be less or equal 7!D:\bin\tasm\EXAMPLE\duodec>duodec.exe? 10 = 8D:\bin\tasm\EXAMPLE\duodec>duodec.exe? 14 = 10Как видим, переход на десяток в восмеричной системе происходит на 8-ми (10 = 😎 А переход на 10 в 12-рич. системе происходит при 12 (14 в восмерич.) (14 = 10)Файл duodec.def:CODE PRELOAD MOVEABLE DISCARDABLEDATA PRELOAD MOVEABLE MULTIPLEHEAPSIZE 65536STACKSIZE 65536Файл make.bat:@echo offcls..\..\BIN\tasm32 /mx /m4 /z duodec.asm..\..\BIN\tlink32 -x -V4.0 -Tpe -ap -c duodec.obj,duodec,,,duodec.defif errorlevel == 1 goto failuredel *.objecho duodec.exe createdgoto end:failureecho error!:endpauseФайл duodec.asm:.386.model flat, stdcalllocalsincludelib ..\..\LIB\imp32i.libinclude ..\..\INCLUDE\w32.inc;extrnprintf: PROCextrn_getch: PROCextrn _putch: PROC;.DATAbufdb 32 dup(?) quest db “? “, 0fmtSdb “%s”, 0fmtDdb “%d”, 0equaldb ” = “, 0errMdb”input error: digit must be less or equal 7!”, 0.DATA?;.CODEstart:pushad; сохраним регистрыmov si, 8; так как исходная с-ма восьмеричная (потом будем умножать на 8 )mov ebx, 0; здесь будет введенное число после перевода его из ascii в числоcall printf, offset quest ; выводим ‘?’add esp, 4; восстановим стекnext:mov eax, 0; обнулим eaxcall_getch; ожидаем ввода символа cmp ax, 20h; если пробел, то конец вводаje endinput; переходим на преобразование числаmov ah, 0 ; дальше переводим ascii символ, в число (например код ‘1’ равен 0x31 )and al, 00001111b ; теперь ax = 1 (сначало было например 0x31)mov di, ax ; временно запомним cmp ax, 7; если введенная цифра больше 7, то ошибкаjle cont; переход на продолжние работыcall printf, offset errM ; печатаем сообщение об ошибкеadd esp, 4; восстанавливаем стекjmp exit; переход на конец программыcont:call printf, offset fmtD, eax; печатаем очередную введенную цифруadd esp, 8; восстанавливаем стекmov ax, bx ; временно запомним bxmul si ; умножим ax на 8 (si = 😎 add ax, di ; сложим с уже введенным числом (накапливаем сумму)mov bx, ax ; запомним результатloop next ; перейдем на считывание следующего символаendinput:call printf, offset equal ; выводим знак ‘=’add esp, 4; восстановим стекmov edx, ebx; введенное число в dxcall duodec; преобразуем и печатаем число в 12-рич. системуexit:popad; восстановим регистрыcallExitProcess, 0; вызов завершения программы (в Windows)ret; конец программы;;proc – подпрограмма, перевод числа в dx в 12-чную с-му и вывод на экранduodec: mov ebx, offset buf ; в bx адрес начала буфера; переводим число в ascii (в 12-чной сис-ме и складываем в буфер в обратном порядке)label0:mov si, 12; будем делить на 12mov ax, dx; число в axsub dx, dx; преобразуем AX в двойное слово в AX:DXdiv si ; делим число на 12 (получаем dx – остаток, ax – частное)cmp dl, 9 ; сравним, если число <= 9, то прибавим '0' иначе 'a'jle label1add dl, 87 ;число - 10 + 'a' mov byte ptr [ebx], dl ; запишем букву в буферjmp label2label1:add dl, 48 ; число + '0'mov byte ptr [ebx], dl ; запишем букву в буферlabel2:add bx, 1 ; увеличим указатель на буфер на 1mov dx, ax; частное в dx cmp dx, 0 ; проверим на 0 и если не равно, еще один циклjg label0; выводим буфер на печать в обратном порядке (на печать выходит в прямом)label4:sub bx, 1 ; уменьшим указатель на буфер, так сейчас он указывает за последнуюю буквуxor edx, edx; обнуляем edxmov dl, byte ptr [ebx] ; в dl буква по указателюcall _putch, edx; выводим букву в станд. вывод (на экран например)add esp, 4; восстанавливем стекmov eax, offset buf; в ax начало буфераcmp eax, ebx ; проверим не дошли ли мы до начала буфераjne label4 ; если нет, цикл еще разret; конец подпрограммыEND start