РАССЫЛКИ ПОРТАЛА RFPRO.RU Лучшие эксперты по данной тематике Номер выпуска: | 1574 | Дата выхода: | 18.12.2015, 01:21 | Администратор рассылки: | Лысков Игорь Витальевич (Старший модератор) | Подписчиков / экспертов: | 17 / 7 | Вопросов / ответов: | 1 / 1 | Консультация # 188411: Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: По запросу программы пользователь вводит с клавиатуры два целых четырехзначных положительных десятичных числа, разделённых знаком операции + или - Программа выводит на экран результат операции в двух системах счисления : в десятичной и бинарной (в дополнительном коде).<... Консультация # 188411: Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: По запросу программы пользователь вводит с клавиатуры два целых четырехзначных положительных десятичных числа, разделённых знаком операции + или - Программа выводит на экран результат операции в двух системах счисления : в десятичной и бинарной (в дополнительном коде).
Для перевода числа из десятичной системы счисления в любую другую воспользуйтесь алгоритмом вывода на экран десятичных и шестнадцатеричных чисел:

Ассемблер: Nasm
Спасибо. Дата отправки: 13.12.2015, 00:45 Вопрос задал: surikalex007456 (Посетитель) Всего ответов: 1 Страница онлайн-консультации » Консультирует Лысков Игорь Витальевич (Старший модератор): Здравствуйте, surikalex007456! Вот и программа. Работает как с положительными, так и с отрицательными числами Комментариев более, чем достаточно. Вникайте...
Код (Assembler): format PE console include 'win32ax.inc' code ;функция преобразует строку в число ;первые пробелы пропускаются ;ввод заканчивается любой нецифрой ;параметры: ;esi - адрес строки ;ecx - длина строки ;число возвращается в eax proc atoi uses edi ebx mov ebx, 1 ;знак числа, считаем, что положительное mov edi, 10 ;будем умножать на 10 xor edx, edx ;здесь накапливаем число first_spaces: ;цикл пропуска первых пробелов lodsb ;читаем символ из [esi], esi++ dec ecx ;уменьшаем счетчик jl .atoi_ret ;строка кончилась cmp al, ' ' ;первые пробелы je .first_spaces ; пропускаем cmp al, '-' ;встретили минус? jne .atoi_next neg ebx ;ebx = -1, отрицательное число lodsb ;читаем следующий символ dec ecx ;уменьшаем счетчик jl .atoi_ret ;строка кончилась atoi_next: ;цикл обработки цифр cmp al, '0' ;проверяем на цифру jl .atoi_ret cmp al, '9' jg .atoi_ret imul edx, edi ;умножаем старшие разряды на 10 and eax, 0x0f ;и добавим add edx, eax ; новый разряд lodsb ;читаем следующий символ dec ecx ;счетчик jge .atoi_next ;и на повтор atoi_ret: dec esi ;сдвинем указатель на предыдущий символ ; для дальнейшего анализа inc ecx ;подправим и счетчик mov eax, edx ;вернем число imul eax, ebx ;учтем знак числа ret endp ;функция анализирует символ операции ;параметры: ;esi - адрес строки ;ecx - длина строки ;код операции возвращается в eax и C=0 ;если символ операции неверный, то вернет C=1 proc GetOp lodsb ;читаем символ dec ecx ;счетчик jl .error cmp al, ' ' ;пробелы игнорируем je GetOp cmp al, '-' ;есть минус je .minus cmp al, '+' ;плюс jne .error xor eax, eax ;для плюса возвращаем 0 clc ret minus: mov eax, 1 ;для минуса - 1 clc ret .error: stc ret endp ;функция парсит введенную строку и вычисляет операцию ;параметры: ;esi - адрес строки ;ecx - длина строки ;результат возвращается в eax и в С proc CalcCommand call atoi ;получаем первое число mov edi, eax ;сохраним в edi call GetOp ;вводим код операции jc .return ;ошибка? mov ebx, eax ;сохраняем в ebx call atoi ;вводим второе число ;проверим на корректность данных cmp byte [esi], 0dh ;мы должны выйти из анализа либо по 0dh je .test_op cmp byte [esi], ' ' ;либо по пробелу stc ;вдруг ошибка! jne .return ;все остальное - ошибка формата! ;все ок! test_op: ;проверяем код операции xchg eax, edi ;поменяем местами операнды test ebx, ebx ;0 - плюс jz .op_add ;1 - минус op_sub: sub eax, edi jmp .ret_ok op_add: add eax, edi ret_ok: clc return: ret endp ;функция преобразования числа в строку ;параметры: ;edi - адрес строки ;eax - число proc itoa test eax, eax ;отрицательное? jge .positive neg eax ;модуль числа mov byte [edi], '-' ;выводим знак минуса inc edi positive: ;собственно преобразование xor ecx, ecx ;счетчик цифр mov esi, 10 ;будем делить на 10 div_loop: ;цикл формирования десятичных разрядов xor edx, edx ;подготавливаемся к делению div esi ;eax - частное edx:eax/esi, edx - остаток push edx ;остаток - очередной разряд - сохраняем в стеке inc ecx ;считаем test eax, eax ;все разряды? jne .div_loop ;нет - на повтор digits_loop: ;цикл вывода цифр, извлекаем из стека в обратном порядке pop eax ;очередной разряд or al, '0' ;делаем символ-цифру stosb ;выводдим loop .digits_loop ;по всем ret endp ;функция формирования двоичной строки ;параметры: ;eвi - адрес строки ;eax - число proc form_bin mov edx, eax ;перенесем число для удовства в edx mov ecx, 32 ;32 бита shift_loop: ;цикл по битам mov al, '0' ;al = '0' shl edx, 1 ;C - очередной бит adc al, 0 ;al = '0' + 0 + C ('0' или '1') stosb loop .shift_loop ;по всем mov ax, 'b' ;строку закончим 'b' с нулем! (ah=0) stosw ret endp ;--------------------------------------------------- ;Начало start: ;получим handle консоли для вывода invoke GetStdHandle, STD_OUTPUT_HANDLE cmp eax,-1 je .console_error_exit mov [hStdOut], eax ;сохраним ;получим handle консоли для ввода invoke GetStdHandle, STD_INPUT_HANDLE cmp eax,-1 je .console_error_exit mov [hStdIn], eax ;сохраним ;выводим приглашение для ввода строки invoke WriteConsole, [hStdOut], szMessage, MsgLen, dwWritten, 0 ;вводим строку в буфер sCommand, длина введенной строки будет в dwReaded invoke ReadFile, [hStdIn], sCommand, 64, dwReaded, 0 ;обрабатываем строку lea esi, [sCommand] mov ecx, [dwReaded] call CalcCommand jc .error_exit ;ошибка? ;формируем результат, число в eax lea edi, [sCommand] ;сюда запишем строку результат push eax ;сохраним число для вывода двоичной стоки call itoa ;преобразуем в строку-знаковое десятичное число mov ax, ', ' ;отделим запятой с пробелом stosw pop eax ;восстановим полученное число call form_bin ;формируем двоичную строку ;выведем полученнфй результат, начиная с пояснительной строки ;третьим параметром передается результат вызова подсчета длины строки ;invoke lstrlen, sResult invoke WriteConsole, [hStdOut], sResult, invoke lstrlen, sResult, dwWritten, 0 jmp short .wait_enter error_exit: invoke WriteConsole, [hStdOut], szError, ErrLen, dwWritten, 0 wait_enter: ;ждем нажатие на enter, чтобы не убежало с экрана invoke ReadFile, [hStdIn], sCommand, 1, dwReaded, 0 jmp short .exit console_error_exit: ;При ошибке получения handle консоли выведем MessageBox, в заголовке путь и имя программы invoke MessageBox,HWND_DESKTOP,"Error occured",invoke GetCommandLine,MB_OK exit: invoke ExitProcess,0 data hStdOut dd -1 hStdIn dd -1 szMessage db "Enter operation: " MsgLen = $-szMessage szError db "Incorrect command!" ErrLen = $-szError dwWritten dd 0 dwReaded dd 0 sResult db "Result: " sCommand db 64 dup(?) end start  | Консультировал: Лысков Игорь Витальевич (Старший модератор) Дата отправки: 15.12.2015, 13:45 5 нет комментария ----- Дата оценки: 15.12.2015, 21:36 | Рейтинг ответа: +1 |
Оценить выпуск | Задать вопрос экспертам главная страница | стать участником | получить консультацию техническая поддержка | восстановить логин/пароль Дорогой читатель! Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно! МЫ РАБОТАЕМ ДЛЯ ВАС! |
Комментариев нет:
Отправить комментарий