RFpro.ru: Ассемблер? Это просто! Учимся программировать
Хостинг портала RFpro.ru: РАССЫЛКИ ПОРТАЛА RFPRO.RU
Лучшие эксперты данной рассылки
/ КОМПЬЮТЕРЫ И СОФТ / Программирование / Assembler (Ассемблер)
Вопрос № 183400: Здравствуйте, уважаемые эксперты! Прошу Вас помочь в написании этой программы: Даны 6 чисел, найти среди них максимальное, возвести его в куб и поделить на 16. Заранее благодарю.... Вопрос № 183401: Здравствуйте, уважаемые эксперты! Прошу вас помочь в написании программы: Дана целочисленная матрица в байтовом формате по строкам. Все операции обработки матрицы реализовать только циклами. При необходимости использовать макросы. Размерность 4... Вопрос № 183402: Здравствуйте, уважаемые эксперты! Прошу вас помочь в написании программы: Ввести произвольную символьную строку. Найти в ней первую по алфавиту букву (не просто символ) и вывести на экран. Задача для TASM, model small Заранее спасибо.... Вопрос № 183407: Здравствуйте! У меня возникли сложности с такой задачей: Ввести произвольную символьную строку. Записать все ее буквы в прописном формате (маленькими буквами). Вывести на экран и записать в файл. TASM DOS... Вопрос № 183408: Уважаемые эксперты! Пожалуйста, ответьте на вопрос: Дана двухбайтовая двоичная строка. Найти, сколько раз в ней встречается сочетание 110 и на каких позициях (сформировать массив начальных позиций). TASM DOS... Вопрос № 183411: Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: Даны 6 чисел, найти среди них максимальное, возвести его в куб и поделить на 16. ASM DOS программа должна работать как для положительных так и для отрицательных ч... Вопрос № 183400:
Здравствуйте, уважаемые эксперты! Прошу Вас помочь в написании этой программы: Даны 6 чисел, найти среди них максимальное, возвести его в куб и поделить на 16.
Отправлен: 29.05.2011, 18:32 Отвечает Лысков Игорь Витальевич (Старший модератор) : Здравствуйте, Илья Андреевич! Числа можно вводить как в одной строке, разделенные любым символом, например, пробелом, так и в разных... При вводе чисел проверяется допустимость: ждем числа < 256. Особенность этого примера в том, что максимальное число-байт 0ffh = 255 в кубе и поделенное на 16 дает число, не помещающееся в слово. Поэтому надо выводить число из пары dx:ax Я применил следующий способ: делю предварительно на 10000, по результатам чего либо вывожу остаток, либо сначала целую часть, потом все 4 цифры остатка Код : ;Даны 6 чисел, найти среди них максимальное, возвести его в куб и поделить на 16 .model small .stack 100h N equ 6 .data sGet db 'Enter 6 numbers < 256: $' sOut db 0ah,'Result: $' sTail db ' ^3 / 16 = $' sError db 0ah,'Error. Number may be < 256',0dh,0ah,'$' sAny db 0dh,0ah,'Press any key$' nums db N dup (0) ;буфер для ввода числовой строки (для функции 0ah) sNum db 80 ;максимальный размер буфера sCount db 0 ;реальный размер строки sBuf db 80 dup (?) ;сама строка .code main proc mov ax, @DATA ;настроим сегментные регистры на сегмент данных mov ds, ax mov es, ax repeat: call GetNums ;введем N чисел jz continue ;если в порядке, то продолжаем lea dx, sError ;сообщение об ошибке mov ah, 9 int 21h jmp repeat ;на повтор ввода continue: ;найдем максимальный lea si, nums ;адрес массива чисел mov cx, N ;количество xor bx, bx ;максимальный SearchMax: lodsb cmp al, bl jbe SearchNext mov bl, al ;новый максимальный SearchNext: loop SearchMax lea dx, sOut ;выводим начало сообщения mov ah, 9 int 21h mov ax, bx ;найденное число call PrintMax10000 ;выведем его lea dx, sTail ;закончим сообщение mov ah, 9 int 21h mov ax, bx ;число mul bl mul bx ;в кубе в рег паре dx:ax mov cx, 4 ;разделим на 16 сдвигом вправо dx:ax на 4 бита shiftLoop: clc rcr dx, 1 rcr ax, 1 loop shiftLoop ;результат, в общем случае, все равно будет в dx:ax call PrintNum ;выведем число из dx:ax lea dx, sAny ;press any key mov ah, 9 int 21h mov ah, 0 ;ждем any key int 16h mov ax, 4c00h ;выход в ДОС int 21h main endp PrintNum proc ;вывод беззнакового числа из dx:ax ;у нас число не больше 255*255*255/16 = 1036335 mov bx, 10000 ;сначала разделим на 10000 div bx test ax, ax ;больше 10000? jz SmallNum ;нет - выводим, как обычное число (без лидирующих нулей) push dx ;сохраним 4 младших разряда call PrintMax10000 ;выведем старшие разряды, как обычное число pop ax ;а младшие 4 цифры call Print4digits ;выводим все jmp PrintNumRet SmallNum: ;выводим число без лидирующих нулей mov ax, dx ;само число теперь в dx, как остаток от деления на 10000 call PrintMax10000 ;выводим число из ax PrintNumRet: ret PrintNum endp Print4digits proc ;выводим ровно 4 разряда числа из ax mov bx, 10 ;будем делить на 10 mov cx, 4 ;число цифр Div4digLoop: xor dx, dx ;готовимся к делению dx:ax / bx div bx ;ax - частное, dx - остаток=очередной младшей цифре push dx ;сохраним цифру в стеке loop Div4digLoop mov cx, 4 ;4 цифры mov ah, 2 ;функция вывода Print4digLoop: ;будем выводить в обратном порядке, начиная со старшей шифры pop dx ;восстановим очередной разряд or dl, '0' ;превратим в символ int 21h ;выведем loop Print4digLoop ret Print4digits endp PrintMax10000 proc ;выводим число из ax без незначащих нулей push bx mov bx, 10 ;будем делить на 10 xor cx, cx ;счетчик цифр DivLoop: xor dx, dx ;готовимся к делению dx:ax / bx div bx ;ax - частное, dx - остаток=очередной младшей цифре push dx ;сохраним цифру в стеке inc cx ;посчитаем test ax, ax ;продолжим, пока не 0 jnz DivLoop mov ah, 2 ;функция вывода PrintLoop: ;будем выводить в обратном порядке, начиная со старшей шифры pop dx ;восстановим очередной разряд or dl, '0' ;превратим в символ int 21h ;выведем loop PrintLoop pop bx ret PrintMax10000 endp GetNums proc ;ввод N чисел lea dx, sGet mov ah, 9 int 21h ;приглашение на ввод чисел lea di, nums ;адрес массива чисел lea bp, [di+N] ;адрес за массивом (для контроля конца) GN_ask: lea dx, sNum ;вводим строку с числами mov ah, 0ah int 21h lea si, sBuf ;строка с числами, разделенная разделителями GN_next: cmp di, bp ;массив заполнен? je GN_ok ;да - выходим call stoi ;[si] в число ax jc GN_err ;число больше 255 - ошибка jcxz GN_newline ;дошли до конца строки? stosb ;сохраняем jmp GN_next ;на следующее число в строке GN_newline: ;переходим на новую строку и продолжаем ввод mov ah, 2 mov dl, 0ah int 21h ;переход на новую строку jmp GN_ask ;на запрос новой строки GN_err: or ax, 1 ;FZ == 0 -> ошибка размерности GN_ok: ret ;FZ == 1 -> все ок GetNums endp stoi proc ;преобразование строки [si] в число AX xor bx, bx ;здесь будем стоить число xor cx, cx ;счетчик разрядов stoi_next: lodsb ;очередной символ cmp al, 0dh ;конец стоки? je stoi_eol cmp al, '0' jb stoi_sep ;любая нецифра - разделитель cmp al, '9' ja stoi_sep push ax ;сохраним новый разряд mov ax, 10 mul bx ;умножим старшие на 10 pop dx ;новый and dx, 0fh ;'0'-'9' -> 0-9 add ax, dx ;добавляем новый разряд cmp ax, 255 ;ждем число <=255 ja numError ;больше - ошибка! mov bx, ax ;сохраняем inc cx ;считаем jmp stoi_next ;продолжаем stoi_sep: ;встретили разделитель jcxz stoi_next ;были только разделители - на продолжение ; иначе - конец числа и выходим stoi_eol: ; если числа нет и встретили 0dh - конец строки mov ax, bx ;число возвращаем в ax dec si ;шаг назад, чтобы легче было проанализировать 0dh clc ;признак того, что все ок ret numError: stc ;признак ошибки ret stoi endp end main Примерный вывод: Код : Enter 6 numbers < 256: 3 45 255 45 6 7 Result: 255 ^3 / 16 = 1036335 Press any key ----- Люби своего ближнего, как самого себя
Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Вопрос № 183401:
Здравствуйте, уважаемые эксперты! Прошу вас помочь в написании программы:
Отправлен: 29.05.2011, 18:39 Отвечает F®ost (Модератор) : Здравствуйте, Илья Андреевич! Данная задача уже решалась на портале, см. Ответ # 266812. © Цитата: Лысков Игорь Витальевич (Старший модератор) Вычисление реализовано с помощью макроса с параметрами. Не забываем, что главная диагональ идет с левого верхнего угла до правого нижнего, а побочная - с левого нижнего до правого верхнего. Код : ;Дана целочисленная матрица в байтовом формате по строкам. ;Все операции обработки матрицы реализовать только циклами. ;При необходимости использовать макросы. ;Размерность 4х4. Найти общую сумму элементов главной и побочной диагоналей. GET_NUM MACRO STRING local CetNumStart CetNumStart: lea dx, STRING ; строка приглашения call GetNum ; введем число в AX jc CetNumStart ; повторим, если ошибка endm .model small .stack 100h .data N equ 4 ;матрица array db 1, 2, 3, 4 db -1,-1,-1, 1 db 2, 1, 1, 1 db -1, 3, 2,-4 ;строки сообщений sSum1 db 0dh,0ah,'Diagonal main sum = $' sSum2 db 0dh,0ah,'Diagonal secondary sum = $' sAny db 0dh,0ah,'Press any key$' ;макро для вычисления суммы диагонали ;параметры: ;off - начальное смещение первого байта ;deltaRow - приращение для перехода на следующую строку ;deltaColumn - приращение для перехода на следующий столбец ;string - адрес строки сообщения для вывода суммы SUMDIAG MACRO off, deltaRow, deltaColumn, string local sum_loop ;локальная метка mov bx, off ;база первого байта (строка) xor si, si ;смещение байта mov al, 0 ;сумма mov cx, N ;число элементов sum_loop: ;цикл суммирования add al, array[bx+si];складываем со следующим элементом add bx, deltaRow ;переходим на следующую строку add si, deltaColumn ;на следующий столбец loop sum_loop ;по всем элементам диагонали cbw ;преобразуем байт в слово lea dx, string ;адрес сообщения call PrintNum ;выведем ENDM .code start: mov ax, @data ;настроим сегментные регистры mov ds, ax mov es, ax ;посчитаем сумму главной диагонали SUMDIAG 0, N, 1, sSum1 ;сумма побочной диагонали SUMDIAG ((N-1)*N), -N, 1, sSum2 lea dx, sAny ;выведем 'Press any key' mov ah, 9 int 21h mov ah, 0 ; ждем нажатие на клавишу int 16h mov ax,4c00h ; конец работы int 21h PrintNum proc ; вывод знакового числа из AX push ax mov ah, 9 int 21h ; вывод строки (из DX) pop ax test ax, ax ;проверим на знак jns form_str ;для положительного на вывод push ax ;для отрицательного выводим - и меняем знак mov dl,'-' ;знак - mov ah, 2 int 21h pop ax neg ax ;меняем знак числа на +, теперь оно положительное form_str: mov bx, 10 ; будем делить на 10 xor cx, cx ; счетчик цифр div_loop: ; цикл получения десятичных разрядов xor dx, dx ; подготовимся для очередного деления div bx ; в dx остаток - очередной десятичный разряд push dx ; сохраним в стеке (от младшего к старшему) inc cx ; посчитаем test ax, ax ; есть еще десятичные разряды? jnz div_loop ; продолжим mov ah, 2 pr_loop: ; цикл вывода десятичных цифр-символов pop dx ; востановим очередной разряд (от старшего к младшему) add dl, '0' ; символ цифры int 21h ; вывод loop pr_loop ; по всем цифрам ret PrintNum endp ; end start © Цитата: Лысков Игорь Витальевич (Старший модератор) Вывод программы: Код : Diagonal main sum = -3 Diagonal secondary sum = 3 Press any key
Ответ отправил: F®ost (Модератор) Оценка ответа: 5
Вопрос № 183402:
Здравствуйте, уважаемые эксперты! Прошу вас помочь в написании программы:
Отправлен: 29.05.2011, 18:41 Отвечает Лысков Игорь Витальевич (Старший модератор) : Здравствуйте, Илья Андреевич! Программа ищет минимальную, в лексикографическом порядке, букву (все английские, естественно, получаются меньше русских). При этом учтены и русские буковки Ё и ё, которые, в общем-то, выпадают из общего порядка букв. По программе, они точно за буквами Е и е, соответственно... Код : ;Ввести произвольную символьную строку. ;Найти в ней первую по алфавиту букву (не просто символ) и вывести на экран. .model small .stack 100h .data sString db 'Enter string: $' sResult db 0ah,'Found min letter: $' sPress db 0dh,0ah,'Press any key$' sNoLetters db 0ah,'Letters not found$' ;буфер для ввода строки (для функции 0ah) bBuf db 80 ;максимальный размер буфера bCnt db ? ;реальный размер строки bStr db 80 dup (?) ;сама строка .code main proc mov ax, @data mov ds, ax ;настроим сегмент данных lea dx, sString mov ah, 9 int 21h ;ждем строку lea dx, bBuf mov ah, 0ah int 21h ;вводим строку ;ищем букву с минимальным кодом lea si, bStr ;строка mov ah, 0ffh ;считаем, что букв вообще нет (взяли самый большой код) MainLoop: lodsb ;очередной символ cmp al, 0dh je Print ;дошли до конца cmp al, 41h ;'A' jb MainLoop cmp al, 5ah ;'Z' jbe SearchMin ;большие английские - ищем с минимальным кодом cmp al, 61h ;'a' jb MainLoop cmp al, 7ah ;'z' jbe SearchMin ;малые английские - ищем с минимальным кодом cmp al, 80h ;'А' jb MainLoop cmp al, 0afh ;'п' jbe SearchMin ;большие русские + малые 'а'-'п' - ищем с минимальным кодом cmp al, 0e0h ;'р' jb MainLoop cmp al, 0f1h ;'р'-'я','Ё','ё' ja MainLoop SearchMin: ;проверим на "особые" буквы 'Ё' и 'ё' cmp ah, 0f0h ;минимальная 'Ё'? je L_min_f0 cmp ah, 0f1h ;минимальная 'ё'? je L_min_f1 cmp al, 0f0h ;текущая 'Ё'? je L_f0 cmp al, 0f1h ;текущая 'ё'? je L_f1 CmpMin: cmp al, ah ;сравниваем jae MainLoop ;больше или равно - игнорируем SetMin: mov ah, al ;меньше - сохраняем, как новый минимальный jmp MainLoop ;читаем дальше L_min_f0: ;минимальная 'Ё' cmp al, 85h ;сравним текущую с 'E' ja MainLoop ;если больше, то игнорируем jmp SetMin ;иначе сохраним, как минимальную L_min_f1: ;минимальная 'ё'? cmp al, 0f0h ;текущая 'Ё'? je SetMin ;она меньше! - сохраним cmp al, 0a5h ;иначе сравним текущую с 'е' ja MainLoop ;если больше, то игнорируем jmp SetMin ;иначе сохраним, как минимальную L_f0: ;текущая 'Ё' cmp ah, 85h ;сравним минимальную с 'E' ja SetMin ;если больше, то сохраняем jmp MainLoop ;иначе игнорируем L_f1: ;текущая 'ё' cmp ah, 0f0h ;минимальная 'Ё'? je MainLoop ;игнорируем cmp ah, 0a5h ;сравним минимальную с 'е' ja SetMin ;если больше, то сохраняем jmp MainLoop ;иначе игнорируем Print: ;выводим cmp ah, 0ffh ;буквы были? je NoLetters ;не было - вводим сообщение push ax ;сохраним минимальную буковку lea dx, sResult mov ah, 9 int 21h ;результат pop ax ;восстановим букву в ah mov dl, ah ;для вывода mov ah, 2 ;ф-я вывода int 21h jmp Exit ;на конец NoLetters: ;сообщение о том, что букв нет lea dx, sNoLetters mov ah, 9 int 21h Exit: lea dx, sPress ;выведем приглашение нажать на любую клавишу mov ah, 9 int 21h mov ah, 0 ;ждем int 16h mov ax, 4c00h int 21h ;выход в ДОС main endp end main Примерный вывод программы: Код : Enter string: опрстёщш Found min letter: ё Press any key ----- Люби своего ближнего, как самого себя
Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Вопрос № 183407:
Здравствуйте! У меня возникли сложности с такой задачей:
Отправлен: 29.05.2011, 20:43 Отвечает Лысков Игорь Витальевич (Старший модератор) : Здравствуйте, Посетитель - 375878! Вот Вам программа: Код : ;Ввести произвольную символьную строку. ;Записать все ее буквы в прописном формате (маленькими буквами). ;Вывести на экран и записать в файл. .model small .stack 100h .data sGetStr db 'Enter string: $' sResult db 0ah,'Result string:$' sGetName db 0dh,0ah,'Enter file name: $' sPress db 0dh,0ah,'Press any key$' ;буфер для ввода строки (для функции 0ah) bBuf db 80 ;максимальный размер буфера bCnt db ? ;реальный размер строки bStr db 80 dup (?) ;сама строка ;буфер для ввода имени файла (для функции 0ah) bBufN db 80 ;максимальный размер буфера bCntN db ? ;реальный размер строки bStrN db 80 dup (?) ;сама строка .code main proc mov ax, @data mov ds, ax ;настроим сегмент данных lea dx, sGetStr mov ah, 9 int 21h ;ждем строку lea dx, bBuf mov ah, 0ah int 21h ;вводим строку ;меняем большие английские на малые lea si, bStr ;строка MainLoop: lodsb ;очередной символ cmp al, 0dh je Print ;дошли до конца cmp al, 41h ;'A' jb MainLoop cmp al, 5ah ;'Z' ja MainLoop ;все остальные оставляем без изменения or al, 20h ;малые отличаются от больших на 20h mov byte ptr [si-1], al ;запишем на место jmp MainLoop Print: ;выводим mov byte ptr [si-1], '$' ;закроем строку '$' для ф-и 09h lea dx, sResult mov ah, 9 int 21h ;результат lea dx, bStr ;ah по-прежнему = 9 int 21h ;строка строка lea dx, sGetName mov ah, 9 int 21h ;ждем имя файла lea dx, bBufN mov ah, 0ah int 21h ;вводим имя файла xor bx, bx mov bl, bCntN ;адрес байта за строкой mov byte ptr bStrN[bx], 0 ;меняем код 0dh на 0 lea dx, bStrN ;имя файла mov ah, 3ch ;ф-я создания файла xor cx, cx ;без атрибутов int 21h mov bx, ax ;описатель файла lea dx, bStr ;адрес буфера mov cl, bCnt ;длина буфера, ch = 0 mov ah, 40h ;ф-я записи int 21h mov ah, 3eh ;ф-я закрытия файла int 21h lea dx, sPress ;выведем приглашение нажать на любую клавишу mov ah, 9 int 21h mov ah, 0 ;ждем int 16h mov ax, 4c00h int 21h ;выход в ДОС main endp end main Примерный вывод программы: Код : Enter string: ASDFasdfъх12345 Result string:asdfasdfъх12345 Enter file name: test.txt Press any key ----- Люби своего ближнего, как самого себя
Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Вопрос № 183408:
Уважаемые эксперты! Пожалуйста, ответьте на вопрос:
Отправлен: 29.05.2011, 20:46 Отвечает Зенченко Константин Николаевич (Модератор) : Здравствуйте, Посетитель - 375878! Смотрите приложение: Код : model tiny code org 100h begin: mov cx,string;исходное число mov bx,0110b;исходное значение mov dx,0111b;маска поиска xor ax,ax;счетчик бит lea di,dwArray;адрес массива @01: push cx;запоминаем число and cx,dx;накладываем маску xor cx,bx;сравниваем jnz @@02;несовпало перехаод stosb;записываем позицию inc byte ptr count;увеличиваем счетчик совпадений @02: pop cx;востанавливаем число inc ax;следующий бит shl bx,1;сдвигаем исходное значение shl dx,1;сдвигаем максу jnc @@01;пока нет переполнения проверяем xor ax,ax;ждем любую клавишу int 16h; ret;выход string dw 1100010110101110b count db 0 dwArray label byte end begin Работу программы можно посмотреть в отладчике, к примеру DEBUG.EXE Удачи! ----- Итерация от человека. Рекурсия — от Бога. — Л. Питер Дойч
Ответ отправил: Зенченко Константин Николаевич (Модератор)
Вопрос № 183411:
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Отправлен: 29.05.2011, 22:47 Отвечает Лысков Игорь Витальевич (Старший модератор) : Здравствуйте, Посетитель - 375878! Для сравнения знаковых чисел надо использовать соответствующие команды... Кроме того, у Вас было неправильно реализовано и увычисление куба с делением на 16. Не учли, что при возведении числа-байта в куб получается два байта И даже после деления на 16, остается словом (Проверьте в калькуляторе для максимального байтового знакового числа 127) Код : .286 model tiny stack 256 data array db 2, 1, 4, 7,5 arsize db $ - array code start: mov ax, @data ; Заносим информацию в посредник mov ds, ax ; и передаем ее регистру DX mov cl, arsize ; Количество элементов в массиве mov di, offset array ; Присваеваем DI адресс начала массива mov bl, [di] ; В BL будет первый элемент max: inc di ; Двигаем указатель на след элемент dec cx ; Уменьшаем CX mov al, [di] ; Присваевам AL новое значение cmp al, bl ; Сравниваем jl skip ; Если меньше пропускаем !!!!!!!!!!!!!!!!!!!!!! jl - знаковое сравнение, jb - беззнаковое mov bl, al ; Если больше присваеваем skip: jcxz endprog ; Если CX == 0 выходим из программы jmp max ; Переходим в начало цикла max endprog: ; mov al, bl ; cbw ; mul bl ; mul bl ; mov bl, 16 ; div bl ; После операции деления в al будет целая ; ; часть в ah дробная ;Дальнейшие вычисления надо переделать: ;умножение трех байт может дать два слова, а не одно ;и даже после деления результат может быть больше слова! ;(проверьте в калькуляторе для числа 127) mov al, bl cbw mov bx, ax ; bx - знаковое слово imul bl ; ax = bl * bl imul bx ; результат в dx:ax mov bx, 16 idiv bx ; целая часть в ax, дробная в dx nop ;--------- mov ax, 4C00h int 21h end start ----- Люби своего ближнего, как самого себя
Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Оценить выпуск »
Задать вопрос экспертам этой рассылки »Скажите "спасибо" эксперту, который помог Вам!Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТАна короткий номер 1151 (Россия) Номер ответа и конкретный текст СМС указан внизу каждого ответа.
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов) © 2001-2011, Портал RFPRO.RU, Россия
Авторское право: ООО "Мастер-Эксперт Про" Калашников О.А. | Гладенюк А.Г. Хостинг: Компания "Московский хостер" Версия системы: 2011.6.31 от 07.05.2011 |
В избранное | ||