![>](style_images/1/nav_m.gif)
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.142.195.16] |
![]() |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Здраствуйте. Нужно чтоб программа отображала на экране любое введенное целое число в восьмиричной системе счисления.
Возникла проблема - не понимаю как записать, чтоб пользователь мог вводить любое число. Да и исходник не уверена что правильный. Вобщем кто разбирается подкоректируйте его пожалуйта. Буду очень благодарна! Исходник: ![]() ![]() .MODEL Small .STACK 100h .DATA String db 16 dup (?),'$' ; Резервируем 16 байт для строки StringEnd = $-1 ; Указывает на символ '$' Number = 1 Str_digit db '5.479$' Obrob_digit db 8 dup (?),'$' ; Drob_chast db 8 dup (?),'$' Mes_1 db 0dh, 0ah, "Chislo 6219 v 16-y sisiteme schisleniya - ", "$" Mes_2 db 0dh, 0ah, "Chislo 6219 v 8-y sisiteme schisleniya - ", " $" Mes_3 db 0dh, 0ah, "Chislo 6219 v 2-y sisiteme schisleniya - ", " $" Mes_4 db 0dh, 0ah, "Chislo 0.479 v 16-y sisiteme schisleniya - ", " $" .CODE ORG 100h Start: mov ax,@data mov ds,ax mov es,ax mov ch,16 lea dx,Mes_4 mov ah,09h int 21h call Razdel mov ah,09h lea dx,Obrob_digit int 21h ; mov ah,09h ; lea dx,Drob_chast ; int 21h ; mov ax,dx ; mov bx,16 ; jmp Proverka_num call Perevod lea dx,Mes_2 mov ah,09h int 21h mov ax,Number mov bx,8 lea di,StringEnd-9 call Perevod_num mov ah,09h lea dx,String int 21h Perevod_num proc push dx push di push cx xor cx,cx Proverka_num: xor dx,dx div bx xchg ax,dx add al,'0' cmp al,'9' jbe Cifra add al,'A'-('9'+1) Cifra: stosb xchg ax,dx inc cx test ax,ax jne Proverka_num pop cx pop di pop dx ret Perevod_num endp end Start |
Сообщ.
#2
,
|
|
|
Помогите пожалуйсто!
|
Сообщ.
#3
,
|
|
|
Лови, Deffi.
Все за тебя делать не стал, но ввод и преобразование строки в число показал. Компилируй и линкуй: tasm /zn filename.asm tlink filename.obj По ссылке Сложение чисел посмотри. Там немного прокомментирован перевод числа в десятичное представление. Восьмеричное - почти то же самое, только основание системы - 8. Для ввода строки я использовал функцию DOS 0Ah. Она вводит в буфер следующего формата: 0-й байт - максимально вводимое число символов + 1 (на символ перевода строки - CR) 1-й байт - по возвращении из int 21h здесь будет длина введенной строки (без учета CR) 2-й байт - начало буфера ввода, его длина равна числу в 0-м байте. Т.к. максимальное число, умещающееся в слове (двух байтах) равно 65535, то длину буфера я выбрал равной 5+1=6 байтам. ![]() ![]() .MODEL Small .DATA KeyBuf db 6, 0, 6 dup(0) ;max,len,string,CR(0dh) CR_LF db 0Dh, 0Ah, '$' Prompt db 'Введите число: ', '$' Res10 db 'Введено число (десятичное ): ', '$' Res08 db 'Введено число (восьмеричное): ', '$' Error01 db 'Ошибка ввода числа',0Dh, 0Ah, '$' Numer dw ? .CODE ; выводит число в регистре AX на экран ; входные данные: ; cx - система счисления (не больше 10) ; ax - число для отображения Show_ax PROC ; mov cx, 10 xor di, di ; di - кол. цифр в числе @@Conv: xor dx, dx div cx ; dl = num mod 10 add dl, '0' ; перевод в символьный формат inc di push dx ; складываем в стэк or ax, ax jnz @@conv ; выводим из стэка на экран @@Show: pop dx ; dl = очередной символ mov ah, 2 ; ah - функция вывода символа на экран int 21h dec di ; повторяем пока di<>0 jnz @@show ret Show_ax ENDP ; преобразования строки в число ; на входе: ; ds:[si] - строка с числом ; ds:[di] - адрес числа ; на выходе ; ds:[di] - число ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен) Str2Num PROC push ax push bx push cx push dx push ds push es push ds pop es mov cl, ds:[si] xor ch, ch inc si mov bx, 10 xor ax, ax @@Loop: mul bx ; умножаем ax на 10 ( dx:ax=ax*bx ) mov [di], ax ; игнорируем старшее слово cmp dx, 0 ; проверяем, результат на переполнение jnz @@Error mov al, [si] ; Преобразуем следующий символ в число cmp al, '0' jb @@Error cmp al, '9' ja @@Error sub al, '0' xor ah, ah add ax, [di] inc si loop @@Loop mov [di], ax clc pop es pop ds pop dx pop cx pop bx pop ax ret @@Error: xor ax, ax mov [di], ax stc pop es pop ds pop dx pop cx pop bx pop ax ret Str2Num ENDP Main PROC FAR mov ax, @DATA mov ds, ax mov es, ax ; ввод числа с клавиатуры (строки) lea dx, Prompt mov ah,09h int 21h mov ah, 0Ah mov dx, offset KeyBuf int 21h ; перевод строки (на новую строку) lea dx, CR_LF mov ah,09h int 21h ; преобразование строки в число lea si, KeyBuf+1 lea di, Numer call Str2Num ; проверка на ошибку jnc @@NoError ; если есть ошибка ввода - напечатать сообщение об ошибке lea dx, Error01 mov ah,09h int 21h jmp @@Exit ; если нет ошибки ввода - напечатать число @@NoError: ; в десятичном представлении lea dx, Res10 mov ah,09h int 21h mov ax, Numer mov cx, 10 call Show_ax lea dx, CR_LF mov ah,09h int 21h ; в восьмеричном представлении lea dx, Res08 mov ah,09h int 21h mov ax, Numer mov cx, 8 call Show_ax lea dx, CR_LF mov ah,09h int 21h ; выход @@Exit: mov ax,4c00h int 21h Main ENDP .STACK 100h END Main |
Сообщ.
#4
,
|
|
|
Заметил у себя ошибку. Если ввести число 65536, то результат будет равен 0. А должно быть сообщение об ошибке.
Нужно добавить строку в процедуру Str2Num ![]() ![]() add ax, [di] jc @@Error ; Если сумма больше 65535 inc si loop @@Loop |
Сообщ.
#5
,
|
|
|
Спасибо огромное Павел. У тебя есть аська, а то есть вопросы, чтоб тут не флудить.
|
Сообщ.
#6
,
|
|
|
К сожалению, нет
![]() |
Сообщ.
#7
,
|
|
|
Ну ладно, тогда вопрос первый как работает твоя программа? Скомпилила и слинковала. Запускаю ехе файл, черный пустой экран, ввожу любое число программа закрывается и все.
|
Сообщ.
#8
,
|
|
|
Цитата Запускаю ехе файл, черный пустой экран Чуть позже я подкорректировал исходник. Добавил "приглашение" - 'Введите число: ' ![]() ![]() ; ввод числа с клавиатуры (строки) lea dx, Prompt mov ah,09h int 21h Цитата Скомпилила и слинковала. Запускаю ехе файл .... ввожу любое число программа закрывается и все. Добавь в конце после метки @@Exit ввод любой клавиши ![]() ![]() @@Exit: ; ожидание нажатия любой клавиши mov ah,01h int 21h mov ax,4c00h int 21h Main ENDP Вот мой exe-шник Прикреплённый файл ![]() |
Сообщ.
#9
,
|
|
|
Приглашение действительно появилось, а вот когда добавила в конце после метки @@Exit ввод любой клавиши - все равно экзешник закрывается при вводе числа.
Скачала файл Input_D.zip, а чем открыть сам файл, он у тебя там без разширения? |
Сообщ.
#10
,
|
|
|
Сейчас еще раз проверил - в архиве два файла Input_D.asm и Input_D.exe. Input_D.asm в кодировке DOS. Input_D.exe запускается и в конце ждет нажатия. Т.е. работает. Покажи еще раз свою программу. Может быть вместо int 21h выполняется int 21 ?
А какой файл в архиве без расширения? Там один exe-шник, другой asm. Сам архив открывается WinZip'ом или WinRar'ом. ![]() ![]() .MODEL Small .DATA KeyBuf db 6, 0, 6 dup(0) ;max,len,string,CR(0dh) CR_LF db 0Dh, 0Ah, '$' Prompt db 'Введите число: ', '$' Res10 db 'Введено число (десятичное ): ', '$' Res08 db 'Введено число (восьмеричное): ', '$' Error01 db 'Ошибка ввода числа',0Dh, 0Ah, '$' Numer dw ? .CODE ; выводит число в регистре AX на экран ; входные данные: ; cx - система счисления (не больше 10) ; ax - число для отображения Show_ax PROC ; mov cx, 10 xor di, di ; di - кол. цифр в числе @@Conv: xor dx, dx div cx ; dl = num mod 10 add dl, '0' ; перевод в символьный формат inc di push dx ; складываем в стэк or ax, ax jnz @@conv ; выводим из стэка на экран @@Show: pop dx ; dl = очередной символ mov ah, 2 ; ah - функция вывода символа на экран int 21h dec di ; повторяем пока di<>0 jnz @@show ret Show_ax ENDP ; преобразования строки в число ; на входе: ; ds:[si] - строка с числом ; ds:[di] - адрес числа ; на выходе ; ds:[di] - число ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен) Str2Num PROC push ax push bx push cx push dx push ds push es push ds pop es mov cl, ds:[si] xor ch, ch inc si mov bx, 10 xor ax, ax @@Loop: mul bx ; умножаем ax на 10 ( dx:ax=ax*bx ) mov [di], ax ; игнорируем старшее слово cmp dx, 0 ; проверяем, результат на переполнение jnz @@Error mov al, [si] ; Преобразуем следующий символ в число cmp al, '0' jb @@Error cmp al, '9' ja @@Error sub al, '0' xor ah, ah add ax, [di] jc @@Error ; Если сумма больше 65535 inc si loop @@Loop mov [di], ax clc pop es pop ds pop dx pop cx pop bx pop ax ret @@Error: xor ax, ax mov [di], ax stc pop es pop ds pop dx pop cx pop bx pop ax ret Str2Num ENDP Main PROC FAR mov ax, @DATA mov ds, ax mov es, ax ; ввод числа с клавиатуры (строки) lea dx, Prompt mov ah,09h int 21h mov ah, 0Ah mov dx, offset KeyBuf int 21h ; перевод строки (на новую строку) lea dx, CR_LF mov ah,09h int 21h ; преобразование строки в число lea si, KeyBuf+1 lea di, Numer call Str2Num ; проверка на ошибку jnc @@NoError ; если есть ошибка ввода - напечатать сообщение об ошибке lea dx, Error01 mov ah,09h int 21h jmp @@Exit ; если нет ошибки ввода - напечатать число @@NoError: ; в десятичном представлении lea dx, Res10 mov ah,09h int 21h mov ax, Numer mov cx, 10 call Show_ax lea dx, CR_LF mov ah,09h int 21h ; в восьмеричном представлении lea dx, Res08 mov ah,09h int 21h mov ax, Numer mov cx, 8 call Show_ax lea dx, CR_LF mov ah,09h int 21h ; выход @@Exit: ; ожидание нажатия любой клавиши mov ah,01h int 21h mov ax,4c00h int 21h Main ENDP .STACK 100h END Main |
Сообщ.
#11
,
|
|
|
Я скачала вот этот архив, Input_D.zip (1.83 кб) открыла WinRar и у меня там один файл Input_D без разширения и все больше ничего нет.
В Tasm можно как-то сделать поддержку русского языка, а то у меня текст крякозяблами отображается? И по поводу экзешника, открываю его появляется приглашения ввода числа, ввожу любое число (экзешник уже не закрывается после ввода) но результаты странные, ввожу число например 64, результат в восьмеричной системе этого числа 8 (правильно я понимаю?) , а появляется в результате 100. Я скриншот прикрепляю, посмотри пожалуйсто. Прикреплённый файл ![]() |
Сообщ.
#12
,
|
|
|
Цитата Deffi @ Сама добавь расширение распакованному файлу Input_D, например ZIP, или RAR. И распакуй еще раз Я скачала вот этот архив, Input_D.zip (1.83 кб) открыла WinRar и у меня там один файл Input_D без разширения и все больше ничего нет. ![]() Цитата Deffi @ Ну так это и есть правильный результат.ввожу число например 64, результат в восьмеричной системе этого числа 8 (правильно я понимаю?) , а появляется в результате 100 Цитата Deffi @ В тасме нельзя В Tasm можно как-то сделать поддержку русского языка, а то у меня текст крякозяблами отображается? ![]() |
Сообщ.
#13
,
|
|
|
Для избавления от кракозябр, нужно текст программы на ассемблере сконвертировать из кодировки Win(1251) в кодировку DOS(866), а затем скомпилировать. Полученный exe-шник будет "говорить по-русски".
Перекодировку можно сделать текстовым редактором AkelPad (скачать можно по ссылке AkelPad объем примерно 25 кБайт) из меню "Кодировки"-"Сохранить в DOS-866". А результат в восьмеричной системе можно проверить в Windows-ком калькуляторе. Пункт меню "Вид" - Инженерный. Набрать число в десятичной системе - Dec, а потом переключиться в восьмеричную систему - Oct. Очень наглядно видно, что 6410=1008. Добавлено Сейчас немного "погулял" по форуму, встретил несколько ссылок по системам счисления: Системы счисления. перевода чисел в другую систему счислени |
Сообщ.
#14
,
|
|
|
![]() ![]() ; преобразования строки в число ; на входе: ; ds:[si] - строка с числом ; ds:[di] - адрес числа ; на выходе ; ds:[di] - число ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен) Str2Num PROC push ax ; сохранение используемых регистров при входе в подпрограмму push bx push cx push dx push ds push es push ds ; регистр es=ds - случайно остались две строки :) - можно удалить pop es mov cl, ds:[si] ; для цикла LOOP устанавливаем счетчик - т.е. сколько xor ch, ch ; символов в строке нужно обработать inc si ; переходим к первому символу в строке (ds:si - содержит адрес) mov bx, 10 ; множитель для каждой цифры xor ax, ax ; начальное значение результата приравниваем к нулю @@Loop: mul bx ; умножаем ax на 10 ( dx:ax=ax*bx ) mov [di], ax ; сохраняем результат, игнорируя старшее слово cmp dx, 0 ; проверяем, результат на переполнение jnz @@Error mov al, [si] ; Преобразуем следующий символ в число cmp al, '0' ; проверяем на то, что в al находится символ цифры от '0' до '9' jb @@Error ; если не символ цифры - тогда ошибка cmp al, '9' ja @@Error sub al, '0' xor ah, ah ; в ax сейчас число соответствующее цифре add ax, [di] ; сложить цифру (ax) с текущим результатом jc @@Error ; Если сумма больше 65535 inc si ; перейти к адресу следующего символа цифры loop @@Loop mov [di], ax ; сохранить результат clc ; сбросить флаг CY - ошибки нет pop es ; восстановить регистры pop ds pop dx pop cx pop bx pop ax ret @@Error: xor ax, ax ; в случае ошибки записать результат равным нулю mov [di], ax stc ; и установить флаг переноса CY - ошибка при преобразовании строки pop es ; восстановить регистры pop ds pop dx pop cx pop bx pop ax ret Str2Num ENDP Идея примерно следующая: На входе имеется 1) адрес строки в формате: длина_строки (1 байт), строка (несколько байт); 2) адрес, по которому будет находиться результат (2 байта). После завершения подпрограммы 1) если сброшен бит CY (переноса), то по второму адресу будет записано число, соответсвующее строке; 2) если флаг CY установлен, то значит во время преобразования произошла ошибка (или результат должен был быть больше 65535, или в строке присутствовали не только цифры но и лишние символы). Давай посмотрим по шагам для строки '987'. При входе в п/п ds:si указывает на строку db 3, '987' (si=адресу ячейки памяти с числом 3) Перед входом в цикл LOOP после всех присвоений имеем cx=3, ax=0, ds:si - равен адресу символа '9', bx=10. Вошли в цикл. dx:ax=ax*bx=0*10=0 (т.е. dx=0 и ax=0) Записали в результат значение ax - ds:[di]=ax=0 Проверяем на переполнение (результат не превышает 65535 - т.е. dx должен быть равен 0) - все в порядке. По адресу ds:[si] считываем в al символ цифры (mov al, [si]) - al='9'. Проверяем, чтобы '0' <= al <= '9' - да, условие выполняется. Из al вычитаем число, соответствующее коду символа '0' - теперь al=9 (и ax=9). Складываем с результатом (по адресу ds:[di]) - ax=0+9=9. Проверяем, не было ли переполнения при сложении (число больше 65535) - нет не было. Адрес указателя ds:si увеличиваем на 1 - теперь в ds:[si] адрес символа '8' - это для следующего прохода. Оператор loop вычитает из cx единицу и проверяет cx=0? Нет cx=cx-1=3-1=2 <> 0. Переход к метке @@Loop. Дальше для ускорения описания пропущу проверки. Снова проходим цикл с метки @@Loop. dx:ax=ax*bx=9*10=90. Результат (ds:[di]) приравниваем к ax=90. Считываем в al символ из адреса ds:[si] - т.е. al='8' Вычитаем из al код символа '0' - al=8 (ax=8). Складываем с результатом (по адресу ds:di) - ax=90+8=98. Адрес указателя ds:si увеличиваем на 1 - теперь в ds:[si] адрес символа '7' - это для следующего прохода. Оператор loop вычитает из cx единицу и проверяет cx=0? Нет, cx=cx-1=2-1=1 <> 0. Переход к метке @@Loop. Снова проходим цикл с метки @@Loop. dx:ax=ax*bx=98*10=980. Результат (ds:[di]) приравниваем к ax=980. Считываем в al символ из адреса ds:[si] - т.е. al='7' Вычитаем из al код символа '0' - al=7 (ax=7). Складываем с результатом (по адресу ds:di) - ax=980+7=987. Адрес указателя ds:si увеличиваем на 1 - теперь в ds:[si] адрес за символом '7' - хоть и некорректный, но это ведь последний проход цикла. Оператор loop вычитает из cx единицу и проверяет cx=0? Да, cx=cx-1=1-1=0 == 0. Переход к следующему за Loop оператору. По адресу ds:[di] записывается содержимое ax=987. Сбрасывается флаг переноса CY - нет ошибки преобразования. Восстанавливаются регистры (их содержимое теперь равно тому, что было перед входом в подпрограмму) - это можно делать, т.к. результат возвращается не в регистре, а в памяти по адресу ds:[di]. Если на вход подпрограммы подать некорректные данные, то во время одной из проверок произойдет переход на метку @@Error. Тогда там обнуляется регистр ax (xor ax, ax) и значение ax (т.е. ноль) записывается в ds:[di]. А также устанавливается признак ошибки - флаг переноса CY. Потом восстанавливаются регистры. В общем, весь алгоритм напоминает схему Горнера - ( 9*10 + 8 )*10 + 7 = 987. "Несколько" коряво, но вроде бы понятно (надеюсь)... У-ух. Набрал... ![]() |
Сообщ.
#15
,
|
|
|
Спасибо, Павел! Столько набрал, я даже не ожидала
![]() Если возникнут еще вопросы я напишу сюда, хотя врядли после такого подробного коментария. P.S С НОВЫМ ГОДОМ! Желаю тебе крепкого здоровья, удачи, финансового благополучия, ну и чтоб все то добро, которое ты делаешь другим людям вернулось тебе в трехкратном размере ![]() |