комсомольск-на-амуре |
|
|
|
|||||||
|
||||||||||
ФОРУМ / КОМПЬЮТЕРЫ И МОБИЛЬНЫЕ ТЕХНОЛОГИИ / Assembler | |||||||||||
создать новую тему написать сообщение | |||||||||||
18:21 28 мая 2009 |
|
||||||||||
|
Народ помогите кто чем может нужно написать прогу для перевода из Восьмеричной системы счисления в Двеннадцатиричную на Асме....Вот Есть код для 8 to 16, а надо 8 to 12 title a10.exe -- from 8 to 16 code segment assume cs:code main: mov si,8 again: mov bx,0 mov dl,'?' call d1 mov cx,6 next: call kbin cmp al,' ' je back mov ah,0 and al, 00001111b mov di, ax mov ax, bx mul si add ax, di mov bx, ax loop next back: mov dl,'=' call d1 mov dx,bx call hexw mov dl,'H' call d1 call crlf jmp again ;---------- subroutines -------------- d1 proc mov ah,2 int 21h ret d1 endp kbin proc near mov ah,1 int 21h ret kbin endp hex proc near mov ax,cs ; push ds mov ds, ax ; set ds=cs push dx mov bx, offset t1 mov al, dl clc shr al,1 shr al,1 shr al,1 shr al,1 xlatb ; translate mov dl, al call d1 pop ax and al, 00001111b xlatb ; translate mov dl, al call d1 ; pop ds ret t1 db '0123456789ABCDEF' hex endp hexw proc near mov di, dx mov dl, dh call hex mov dx, di call hex mov dl,' ' call d1 ret hexw endp crlf proc near mov dl, 10 call d1 mov dl, 13 call d1 ret crlf endp code ends end main |
||||||||||
13:50 1 июня 2009 |
|
||||||||||
|
если еще актуально, я немного откомментировал код и написал процедурку duodec (переводит число в 12-рич. сис. и выводит его на экран) вот измененный код (процудуру hex оставил на память ) код не компилировал и не отлаживал, написал как есть, поэтому может и не работать title a10.exe -- from 8 to 12 code segment assume cs:code main: mov si,8 ; 8 так как исходная с-ма восьмеричная (потом будем умножать на again: mov bx,0 ; здесь будет введенное число после перевода его из ascii в число mov dl,'?' call d1 ; выводим вопрос mov cx,6 next: call kbin ; считываем символ cmp al,' ' ; если пробел, то конец ввода je back mov ah,0 ; дальше переводим ascii символ, в число (например код '1' равен 0x31 ) and al, 00001111b ; теперь ax = 1 (сначало было например 0x31) mov di, ax ; временно запомним mov ax, bx ; временно запомним (ax = bx = 0 на первой итерации цикла) mul si ; умножим на si (=8) на ax (=0), ax = 0 add ax, di ; сложим с введенным числом (0 + 1) mov bx, ax ; запомним результат loop next ; перейдем на считывание следующего символа back: mov dl,'=' ; выводим = call d1 mov dx,bx call hexw ; переводим двух байтовое число в hex (и выводим в станд.вывод) mov dl,'H' call d1 ; выводим H call crlf ; перевод строки jmp again ; все сначала (новое число) ;---------- subroutines -------------- d1 proc ; пишем в станд. вывод mov ah,2 int 21h ret d1 endp kbin proc near ; читаем со станд. ввода mov ah,1 int 21h ret kbin endp hex proc near ; переводим один символ (один байт) в 16-чную с-му mov ax,cs ; push ds mov ds, ax ; set ds=cs push dx mov bx, offset t1 mov al, dl clc shr al,1 shr al,1 shr al,1 shr al,1 xlatb ; translate mov dl, al call d1 pop ax and al, 00001111b xlatb ; translate mov dl, al call d1 ; pop ds ret t1 db '0123456789ABCDEF' hex endp duodec proc near ; переводим один символ (один байт) в 12-чную с-му mov ax,cs mov ds, ax ; set ds=cs mov bx, offset t2 ; в bx адрес начала буфера ; переводим число в ascii (в 12-чной сис-ме и складываем в буфер в обратном порядке) label0: mov ax, dx ; в ax число cdq idiv 12 ; делим число на 12 (получаем ah - остаток, al - частное) cmp ah, 9 ; сравним, если число <= 9, то прибавим '0' иначе 'a' jle label1 add ah, 87 ;число - 10 + 'a' mov byte ptr [bx], ah ; запишем в буфер jmp label2 label1: add eax, 48 ; число + '0' mov byte ptr [bx], ah ; запишем в буфер label2: add bx, 1 ; увеличим указатель на буфер на 1 mov dx, al ; запишем частное от деления cmp dx, 0 ; проверим на 0 и если не равно, еще один цикл jg label0 ; выводим буфер на печать в обратном порядке (на печать выходит в прямом) label4: sub bx, 1 ; уменьшим указатель на буфер, так сейчас он указывает за последнуюю букву xor dx, dx mov dl, byte ptr [bx] ; в dl буква по указателю call d1 ; выводим букву в станд. вывод (на экран например) mov ax, offset t2 cmp ax, bx ; проверим не дошли ли мы до начала буфера jne label4 ; цикл еще раз ret bf db ' '; буфер, достаточный для размещения строки результата duodec endp hexw proc near ; переводим два символа (dx содежит число) call duodec mov dl,' ' call d1 ret hexw endp crlf proc near ; перевод строки mov dl, 10 call d1 mov dl, 13 call d1 ret crlf endp |
||||||||||
11:35 2 июня 2009 |
|
||||||||||
|
что то не работает, выдает несколько ошибок, в том числе и в последней строчке которой не существует, может кто еще чем помочь может???? Все равно большое спасибо!
|
||||||||||
16:10 2 июня 2009 |
|
||||||||||
|
а чем компилируешь, tasm, masm? какая ось? я тоже может попробую, если время и асм найду. только сейчас заметил, строчка bf db ' '; буфер, достаточный для размещения строки результата ужалась, между ' ' должно быть много пробелов, штук 20 например (чтобы число влезло) |
||||||||||
18:20 3 июня 2009 |
|
||||||||||
|
компилирую тасмом...что то все равно ничего не получается..(((
|
||||||||||
15:35 6 июня 2009 |
|
||||||||||
|
Наконец-то появилось время (суббота
) Если все еще актуально, вот работающая версия (под Windows). Компилировал Tasm32(5.3), отлаживал odbg(1.10) Скомпилировать проще всего так: 1. Распаковать Tasm в какую-нибудь дир., например d:\bin\tasm 2. В дир. Examples создать дир. duodec 3. В дир. duodec создать файл duodec.asm с исходным кодом 4. Тут же (в duodec) создать файл duodec.def 5. B тут же создать файл make.bat Для компиляции выполнить make.bat После запуска программа выводит знак '?'. Дальше можно ввести 8-ричное число (цифры должны быть меньш После ввода числа нужно ввести пробел. Программа распечатает число в 12-рич. сис. счисл. Пример работы: D:\bin\tasm\EXAMPLE\duodec>duodec.exe ? 0 = 0 D:\bin\tasm\EXAMPLE\duodec>duodec.exe ? 1 = 1 D:\bin\tasm\EXAMPLE\duodec>duodec.exe ? 7 = 7 D:\bin\tasm\EXAMPLE\duodec>duodec.exe ? input error: digit must be less or equal 7! D:\bin\tasm\EXAMPLE\duodec>duodec.exe ? 10 = 8 D:\bin\tasm\EXAMPLE\duodec>duodec.exe ? 14 = 10 Как видим, переход на десяток в восмеричной системе происходит на 8-ми (10 = А переход на 10 в 12-рич. системе происходит при 12 (14 в восмерич.) (14 = 10) Файл duodec.def: CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 65536 STACKSIZE 65536 Файл make.bat: @echo off cls ..\..\BIN\tasm32 /mx /m4 /z duodec.asm ..\..\BIN\tlink32 -x -V4.0 -Tpe -ap -c duodec.obj,duodec,,,duodec.def if errorlevel == 1 goto failure del *.obj echo duodec.exe created goto end :failure echo error! :end pause Файл duodec.asm: .386 .model flat, stdcall locals includelib ..\..\LIB\imp32i.lib include ..\..\INCLUDE\w32.inc ; extrn printf : PROC extrn _getch : PROC extrn _putch : PROC ; .DATA buf db 32 dup(?) quest db "? ", 0 fmtS db "%s", 0 fmtD db "%d", 0 equal db " = ", 0 errM db"input error: digit must be less or equal 7!", 0 .DATA? ; .CODE start: pushad ; сохраним регистры mov si, 8 ; так как исходная с-ма восьмеричная (потом будем умножать на 8 ) mov ebx, 0 ; здесь будет введенное число после перевода его из ascii в число call printf, offset quest ; выводим '?' add esp, 4 ; восстановим стек next: mov eax, 0 ; обнулим eax call _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 ; временно запомним bx mul si ; умножим ax на 8 (si = add ax, di ; сложим с уже введенным числом (накапливаем сумму) mov bx, ax ; запомним результат loop next ; перейдем на считывание следующего символа endinput: call printf, offset equal ; выводим знак '=' add esp, 4 ; восстановим стек mov edx, ebx ; введенное число в dx call duodec ; преобразуем и печатаем число в 12-рич. систему exit: popad ; восстановим регистры call ExitProcess, 0 ; вызов завершения программы (в Windows) ret ; конец программы ; ;proc - подпрограмма, перевод числа в dx в 12-чную с-му и вывод на экран duodec: mov ebx, offset buf ; в bx адрес начала буфера ; переводим число в ascii (в 12-чной сис-ме и складываем в буфер в обратном порядке) label0: mov si, 12 ; будем делить на 12 mov ax, dx ; число в ax sub dx, dx ; преобразуем AX в двойное слово в AX:DX div si ; делим число на 12 (получаем dx - остаток, ax - частное) cmp dl, 9 ; сравним, если число <= 9, то прибавим '0' иначе 'a' jle label1 add dl, 87 ;число - 10 + 'a' mov byte ptr [ebx], dl ; запишем букву в буфер jmp label2 label1: add dl, 48 ; число + '0' mov byte ptr [ebx], dl ; запишем букву в буфер label2: add bx, 1 ; увеличим указатель на буфер на 1 mov dx, ax ; частное в dx cmp dx, 0 ; проверим на 0 и если не равно, еще один цикл jg label0 ; выводим буфер на печать в обратном порядке (на печать выходит в прямом) label4: sub bx, 1 ; уменьшим указатель на буфер, так сейчас он указывает за последнуюю букву xor edx, edx ; обнуляем edx mov dl, byte ptr [ebx] ; в dl буква по указателю call _putch, edx ; выводим букву в станд. вывод (на экран например) add esp, 4 ; восстанавливем стек mov eax, offset buf ; в ax начало буфера cmp eax, ebx ; проверим не дошли ли мы до начала буфера jne label4 ; если нет, цикл еще раз ret ; конец подпрограммы END start |
||||||||||
10:43 8 июня 2009 |
|
||||||||||
|
Огромнейшее спасибо, пробую откомпилировать...
|
||||||||||
12:11 10 июня 2009 |
|
||||||||||
|
-sc-, Что то не могу откомпилировать...говорит ошибка...может как нибудь Экзэшник перекинуть можно??? на мыло например?
|
||||||||||
18:02 10 июня 2009 |
|
||||||||||
|
Так вроде откомпилировал, но вот после нажатия пробела....вылетает из проги...что это может быть???
|
||||||||||
18:18 10 июня 2009 |
|
||||||||||
|
так вроде как прогу запустить разобрался, только вот приходится для перевода каждого числа заново запускать прогу...почему выходит? и почему включая семерку и выше не переводит?? |
||||||||||
05:58 12 июня 2009 |
|
||||||||||
|
Семерку она переводит 7 = 7, и 77 тоже переведет. В восьмеричной системе одна цифра не может быть больше 7. Т.е. 77 нормально, а 78 уже нет. Про системы счисления немного написано в вики. Искать гуглом по словам: wiki системы счисления. Программку написал только для перевода одного числа, но если надо больше то вот. Весь текст не привожу,только три кусочка и куда вставить. Чтобы выйти, нужно ввести "неправильный" символ, например Enter. добавим строчку crlf ... вот так: errM db "input error: digit must be less or equal 7!", 0 crlf db 13, 10, 0 .DATA? добавми строчку again: вот так: .CODE start: pushad ; сохраним регистры again: mov si, 8 ; так как исходная с-ма восьмеричная (потом будем умножать на 8 ) и еще пару строчек вот так: call duodec ; преобразуем и печатаем число в 12-рич. систему call printf, offset crlf ; перевод строки add esp, 4 ; восстановим стек jmp again exit: |
||||||||||
06:04 12 июня 2009 |
|
||||||||||
|
Насчет проблем компиляции не знаю. Никаких не было. Путь к tasm32 нужно прописать в переменную окружени path. Tasm у меня такой D:\bin\tasm\EXAMPLE\duodec>tasm32 Turbo Assembler Version 5.0 Copyright (c) 1988, 1996 Borland International Винда XP. Tasm брал на wasm.ru wasm'е в разделе компиляторы Tasm5+. |
||||||||||
09:49 15 июня 2009 |
|
||||||||||
|
Все спасибо большое, не знаю что бы я без вас делал, все сдал....зачет поставил!!!
|
||||||||||
01:47 17 июня 2009 |
|
||||||||||
|
Вопрос не касается первоначального сообщения, но касается ассемблера. Сразу скажу, что это программа учебная, используется ассемблер для DOS, конкретнно - tasm 3.0 Условие такое: имеется две переменные var1 db '1234567890$' var2 db '0987654321$' В определенный момент необходимо присвоить переменной var1 значение переменной var2. Делаю так: mov AX, offset var1 mov var2, AX При компиляции выдает ошибку: Operand types do not match, указывается номер второй строки, в которой пытаюсь в переменную записать из регистра.... Как правильно сделать копирование одной переменной в другую? |
||||||||||
04:42 18 июня 2009 |
|
||||||||||
|
Насколько я понял, под присвоить здесь имеется ввиду скопировать var2 в var1 (побайтно). Это может сделать следующий код (простой, так как учебный
): ; mov ax, offset var1 ; в ax указатель на переменную var1 mov bx, offset var2 ; в bx указатель на переменную var2 label1: mov cl, byte ptr [bx] ; в cl загружаем значение (байт) из адреса в bx (var2) mov byte ptr [ax], cl ; значение в cl записываем (байт) в адрес в ax (var1) ; (таким образом скопировали 1 байт) add ax, 1 ; увеличиваем указатель на 1, так чтобы он указывал на следующий байт переменной var1 add bx, 1 ; увеличиваем указатель на 1, так чтобы он указывал на следующий байт переменной var2 cmp cl, '$' ; сравниваем с $ (концом последовательности) jne label1 ; делаем еще один цикл, если не достигли конца ; После выполнения данного кода переменная var1 будет такой: var1 db '0987654321$' |
||||||||||
17:43 18 июня 2009 |
|
||||||||||
|
mov byte ptr [ax], cl - вот на эту строчку ругается, Illegal indexing mode UPD Из описаний ошибок tasm
|
||||||||||
15:20 21 июня 2009 |
|
||||||||||
|
ну вроде компилятор подсказывает, что вместо ax, bx нужно использовать si, di. Поэтому пробуем такой код: mov di, offset var1 mov si, offset var2 label1: mov al, byte ptr [si] mov byte ptr [di], al add di, 1 add si, 1 cmp al, '$' jne label1 |
||||||||||
18:22 23 июня 2009 |
|
||||||||||
|
Спасибо, помогло!
|
||||||||||
06:02 19 июля 2009 |
|
||||||||||
|
Извините, что влез... так поздно. Вот и ответ на вопрос
"Чему учат программистов в Комсе?"
Тема последнего задания, как я понимаю, что-то вроде "изучение строковых команд". Я бы её не принял, показывает незнание набора инструкций (не отностися к -sc- который давно забыл). Есть однобайтные команды загрузки с автоинкрементом источника (si) и приёмника (di) cld ; сбрасывем флаг направления label1: lodsb stosb cmp al, '$' jne label1 |
||||||||||
20:15 3 ноября 2009 |
|
||||||||||
|
Нет, там было не про строковые команды, приведенный вопрос был лишь эпизодом в курсовой
Сейчас подучил, спрашивать такое не стал бы, да.
|
||||||||||
создать новую тему написать сообщение | |||||||||||
Сервер развивается и
поддерживается редакцией еженедельника «Наш город»
Отдел рекламы: (4217) 20-10-07; adver@komcity.ru Правила использования материалов |
Программирование: 2002—2004
Технодизайн
2005—2013 "Наш город" |