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 Примерный вывод программы: Код : 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 |
| В избранное | ||

