Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты данной рассылки

Boriss
Статус: Академик
Рейтинг: 2671
∙ повысить рейтинг »
Коцюрбенко Алексей aka Жерар
Статус: Профессор
Рейтинг: 2501
∙ повысить рейтинг »
Абаянцев Юрий Леонидович aka Ayl
Статус: Профессионал
Рейтинг: 2214
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / Assembler (Ассемблер)

Номер выпуска:1464
Дата выхода:19.06.2011, 23:30
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:209 / 64
Вопросов / ответов:3 / 3

Вопрос № 183613: Уважаемые эксперты! Пожалуйста, ответьте на вопрос: Повторяю свой вопрос № 183147 -написать программу, считающую количество запятых в файле. Имя файла ввести с клавиатуры или передать как параметр командной строки. Чтение из файла организовать блоко...


Вопрос № 183617: Здравствуйте, уважаемые эксперты! Прошу вас помочь в написании программы: Дана целочисленная матрица в байтовом формате по строкам. Все операции обработки матрицы реализовать только циклами. При необходимости использовать макросы. Размерность 4...
Вопрос № 183618: Здравствуйте, уважаемые эксперты! Прошу вас помочь в написании программы: Ввести произвольную символьную строку из слов, разделенных пробелами. Удалить из строки все большие (заглавные) буквы, сформировав из них отдельную строку и файл. Результат ...

Вопрос № 183613:

Уважаемые эксперты! Пожалуйста, ответьте на вопрос: Повторяю свой вопрос № 183147 -написать программу, считающую количество запятых в файле. Имя файла ввести с клавиатуры или передать как параметр командной строки. Чтение из файла организовать блоком. Размер блока- по усмотрению.Необходимы подробные комментарии на каждой строке.АСС- TASM.В приложении ответ данный Зенченко К.Н. Если можно упростите программу, так как мы только начинаем изучать АСС ? Заранее спасибо, с уважением Canijke.


Отправлен: 14.06.2011, 13:07
Вопрос задал: Canijke (Посетитель)
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, Canijke!

Вот Вам моя версия программы.
Разные подзадачи реализованы в виде подпрограмм.
Программа анализирует сначала параметр командной строки, причем игнорирует лидирующие пробелы и
пробел, также как и код 0dh, является концом имени файла.
Если параметра нет, то имя запрашивается с консоли.
При операциях с файлом проводится проверка на ошибки.

Придется-таки потрудиться, чтобы понять код... Задача достаточно объемная.
Если что непонятно, пишите в мини-форум
Удачи!

Код :
 .model small
 .stack 100h
 .code
start:
 mov ax, @data
 mov es, ax  ;настроим пока только регистр es
    ;ds  равен сегменту PSP, там параметр командной строки
 call GetParm  ;смотрим параметр из командной строки, если есть, 
    ;то dx - смещение имени файла в сегменте данных
 mov ax, @data
 mov ds, ax  ;настроим и ds

 jnc openFile ;если задано, то на открытие файла
    ;не задано - запрашиваем
 lea dx, sGetIn ;строка приглашения 'Enter file name:'
 call GetName  ;ds:dx = адрес имени входного файла

;откроем входной файл
openFile:
 mov ax, 3d00h ;открываем файл на чтение
 int 21h
 jc OpenError ;ошибка?
 mov bx, ax  ;сохраним описатель файла в bx для дальнейшей работы
 xor si, si  ;счетчик запятых
 lea dx, buffer ;адрес буфера
 xor di, di  ;для контроля файла 0 длины
;прочитаем
readLoop:
 mov cx, 1000h ;будем читать 4к за 1 раз
 mov ah, 3fh  ;функция чтения
 int 21h
 jc ReadError ;ошибка?
 mov cx, ax  ;сохраним длину файла в cx
 jcxz printRes ;чтение после конца даст 0 - признак, что все прочитано

 call CalcCommas ;считаем запятые кусочка
 jmp readLoop ;и на повтор

printRes:   ;вывод результата подсчета
 lea dx, sCommasNum ;выведем сообщение
 mov ah, 9
 int 21h

 mov ax, si  ;число запятых
 call PrintNum

closeFile:
 mov ah, 3eh  ;закроем входной файл
 int 21h

PressAny:
 lea dx, sAny ;выведем 'Press any key'
 mov ah, 9
 int 21h

 mov ah, 0  ; ждем нажатие на клавишу
 int 16h

 mov ax,4c00h ; конец работы
 int 21h

;обработка ошибок
OpenError:   ;ошибка открытия (файл или не найден, или занят)
 lea dx, sOpenErr
 mov ah, 9
 int 21h
 jmp PressAny ;на вывод 'Press any key'
ReadError:   ;ошибка чтения
 lea dx, sReadErr
 mov ah, 9
 int 21h
 jmp closeFile ;на закрытие и вывод 'Press any key'

CalcCommas proc  ;подсчет запятых, dx - адрес буфера, cx - длина, результат - si
 mov di, dx  ;адрес начала буфера
 mov al, ','  ;будем искать код ','
calcLoop:
 jcxz calcRet  ;длина 0 - нечего делать
 repne scasb  ;ищем, пока не равно
 jne calcRet  ;не равно, значит дошли до конца
 inc si  ;равно - считаем
 jmp calcLoop ;по всему буферу
calcRet:
 ret
CalcCommas endp

;Подпрограмма ввода имени файла
;на входе:  ds:dx - адрес сообщения
;на выходе: ds:dx - адрес имени
GetName proc
 mov ah, 9  ;выведем приглашение из dx:dx
 int 21h

 lea dx, buf  ;введем строку
 mov ah, 0ah
 int 21h

 xor bx, bx  ;заменим последний код 0dh на 0
 mov bl, len  ;длина введенной строки
 mov byte ptr string[bx], 0 ;пишем 0

 lea dx, string ;возвращаем адрес имени
 ret
GetName endp

;анализ параметра
;адрес параметра в PSP находится по адресу PSP:80h - длина, PSP:81h - сам параметр, 
;заканчивающийся кодом 0dh. Мы длину трогать не будем, а будем анализировать по коду 0dh
;имя файла можно как предворять, так и завершать разделителями (пробелом, табуляцией)
;флагом CF = 0/1 вернем результат: задано/не задано имя файла
GetParm proc
 mov si, 81h  ;параметр в сегменте PSP
 lea di, string ;адрес в сегменте данных, куда запишем имя файла
 mov dx, di  ;здесь вернем адрес имени, если задано, конечно
 xor cx, cx  ;счетчик символов имени файла
parmLoop:
 lodsb   ;очередной
 cmp al, 0dh
 je endParm  ;конец строки
 cmp al, ' '
 je parmSeparator ;разделитель
 cmp al, 9
 je parmSeparator ;разделитель
 stosb   ;символ имени - копируем
 inc cx  ;считаем
 jmp ParmLoop ;по всем

parmSeparator:   ;разделитель
 jcxz parmLoop ;разделители в начале строки пропускаем
endParm:   ;конец строки
 stc   ;сначала пометим, что нет параметра
 jcxz parmRet  ;счетчик символов нет - точно нет параметра
 mov al, 0  ;есть, завершаем строку нулем
 stosb
 clc   ;и помечаем, что параметр задан
parmRet:
 ret
GetParm endp

PrintNum proc  ;вывод беззнакового числа из ax
 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 ax  ;восстановим очередной разряд
 or al, '0'  ;превратим в символ
 int 29h  ;выведем
 loop PrintLoop
 ret
PrintNum endp

 .data

;строки сообщений
sGetIn  db 0dh,0ah,'Enter file name: $'
sCommasNum db 0dh,0ah,'Commas count = $'
sAny  db 0dh,0ah,'Press any key$'

sOpenErr db 0dh,0ah,'File open error!$'
sReadErr db 0dh,0ah,'File read error!$'

buf label byte  ; буфер для приема строки с клавиатуры (по ф-и 0ah)
max db 128  ; максимальная длина строки
len db 0  ; реальная длина введенной строки
string db 128 dup (?) ; сама строка

buffer db 1000h dup(?) ;буфер для чтения файла (размещаем за программой)

 end start

-----
Люби своего ближнего, как самого себя

Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Ответ отправлен: 14.06.2011, 17:56
Номер ответа: 267732
Украина, Кировоград
Тел.: +380957525051
ICQ # 234137952
Mail.ru-агент: igorlyskov@mail.ru

Оценка ответа: 5
Комментарий к оценке:
Спасибо за помощь. Надеюсь разобраться и сдать это задание.

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 267732 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:


  • Вопрос № 183617:

    Здравствуйте, уважаемые эксперты! Прошу вас помочь в написании программы:
    Дана целочисленная матрица в байтовом формате по строкам. Все операции обработки матрицы реализовать только циклами. При необходимости использовать макросы.
    Размерность 4х4. Записать в отдельный массив столбец с максимальной суммой элементов.

    Задача для TASM, model small.
    Прошу как можно подробнее расписать комментарии к программе. Заранее благодарен.

    Отправлен: 14.06.2011, 14:34
    Вопрос задал: oktan (Посетитель)
    Всего ответов: 1
    Страница вопроса »


    Отвечает Лысков Игорь Витальевич (Старший модератор) :
    Здравствуйте, oktan!

    Вот Вам программа. Ничего не вводится и не выводится.
    Исходная матрица чисел со знаком задана в сегменте данных.
    Результирующий массив будете смотреть в отладчике...

    Будут вопросы, пишите в мини-форуме.

    Код :
    ;Дана целочисленная матрица в байтовом формате по строкам. 
    ;Все операции обработки матрицы реализовать только циклами. 
    ;При необходимости использовать макросы.
    ;Размерность 4х4. Записать в отдельный массив столбец с максимальной суммой элементов. 
     
     .model small
    
     .stack 100h
    
    N equ 4  ;размерность матрицы
    
     .data
    array db  1, 2, 3, 4 ;примерная матрица 4х4
     db -1,-2,-3,-4
     db  0, 1, 2, 3
     db  2, 3, 1, 0
    maxcol db N dup (?) ;массив, куда запишем столбец с максимальной суммой элементов
    
     .code
    main proc
     mov ax, @DATA ;настроим сегментные регистры
     mov ds, ax  ;на сегмент данных
     mov es, ax
    
     xor si, si  ;индекс столбца
     mov di, -32767 ;максимальная сумма элементов стобцов 
        ; (в начале - самое маленькое число )
     mov cx, N  ;число слолбцов
    ColumnsLoop:
     push cx  ;сохраним счетчик столбцов
     xor dx, dx  ;сумма элементов текущего стобца
     xor bx, bx  ;база строки матрицы (0, 4, 8, 12)
     mov cx, N  ;число элементов столбца (число строк)
    RowsLoop:   ;цикл подсчета суммы столбца
     mov al, array[bx+si]; очередной байт 
     cbw   ;превратим знаковый байт al в знаковое слово ax
     add dx, ax  ;складываем
     add bx, N  ;на следующую строку
     loop RowsLoop ;по всем элементам столбца
    
     cmp dx, di  ;сравним найденную сумму dx с максимальной di
     jle NextColumn ;если <=, то обходим
     mov di, dx  ;сохраним новую максимальную сумму
     mov bp, si  ;и индекс столбца с максимальной суммой
    NextColumn:   ;переход на новый столбец
     inc si  ;индекс нового столбца
     pop cx  ;восстановим счетчик столбцов
     loop ColumnsLoop ;по всем столбцам
    
        ;макс сумма найдена, сохраним столбец с макс суммой
     lea di, maxcol ;адрес, куда запишем
     xor bx, bx  ;база строки
     mov si, bp  ;индекс столбца
     mov cx, N  ;количество
    CopyLoop:
     mov al, array[bx+si];читаем
     stosb   ;пишем по адресу es:[di], di = di+1
     add bx, N  ;на следующую строку
     loop CopyLoop ;по всем элементам столбца
    
     mov ax, 4c00h ;выход в ДОС
     int 21h
    
    main endp
    
     end main
    

    -----
    Люби своего ближнего, как самого себя

    Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
    Ответ отправлен: 14.06.2011, 16:32
    Номер ответа: 267730
    Украина, Кировоград
    Тел.: +380957525051
    ICQ # 234137952
    Mail.ru-агент: igorlyskov@mail.ru

    Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
    Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 267730 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:


  • Вопрос № 183618:

    Здравствуйте, уважаемые эксперты! Прошу вас помочь в написании программы:
    Ввести произвольную символьную строку из слов, разделенных пробелами. Удалить из строки все большие (заглавные) буквы, сформировав из них отдельную строку и файл. Результат вывести на экран.

    Задача для TASM, model small.
    Прошу как можно подробнее расписать комментарии к программе. Заранее благодарен.

    Отправлен: 14.06.2011, 14:39
    Вопрос задал: oktan (Посетитель)
    Всего ответов: 1
    Страница вопроса »


    Отвечает Лысков Игорь Витальевич (Старший модератор) :
    Здравствуйте, oktan!
    Не дождавшись от Вас ответа в мини-форуме, предлагаю следующую программу:
    1) Удаляем заглавные, получаем две строки: исходную, без заглавных, и строку из одних заглавных
    2) Выводим на экран обе строки (для наглядности)
    3) Имя файла задаем в теле, как uppers.txt, и выводим туда строку из заглавных букв
    4) Учитывает только Английские заглавные, все остальные считаем "остальными"
    5) В случае отсутствия букв любого типа (типа все заглавные или ни одной заглавной), выводится соответствующее сообщение

    Код :
    ;Ввести произвольную символьную строку из слов, разделенных пробелами. 
    ;Удалить из строки все большие (заглавные) буквы, сформировав из них 
    ;отдельную строку и файл. Результат вывести на экран. 
    
     .model small
     .stack 100h
     .code
    main proc
     mov ax, @data ;настроим сегменты данных
     mov ds, ax
     mov es, ax
    
     lea dx, sIn  ;строка приглашения 'Enter string:'
     mov ah, 9
     int 21h
    
     lea dx, buf  ;введем строку
     mov ah, 0ah
     int 21h
    
     lea si, string ;адрес строки
     lea di, uppers ;адрес, куда запишем заглавные буквы
     mov bx, si  ;по старому адресу будем писать все остальные символы
    MainLoop:   ;цикл по строке
     lodsb   ;читаем очередной
     cmp al, 0dh  ;конец строки?
     je PrintResult ;на вывод результата
     cmp al, 41h  ;'A'
     jb SaveOther ;другие сохраним по адресу [bx]
     cmp al, 5ah  ;'Z'
     ja SaveOther ;другие сохраним по адресу [bx]
     stosb   ;заглавные сохраняем по адресу [di]
     jmp MainLoop ;на следующий символ
    SaveOther:   ;остальные
     mov [bx], al ;сохраняем
     inc bx  ;инкремент адреса
     jmp MainLoop ;на следующий символ
    
    PrintResult:   ;вывод результата
     push di  ;сохраним адрес конца в буфере заглавных букв
    
        ;di - адрес конца выводимого буфера (заглавных букв)
     lea dx, sUpOut ;адрес строки 'Upper-case letters:'
     lea bp, uppers ;адрес начала выводимой строки заглавных букв
     call OutMessage ;выводим данные
    
     mov di, bx  ;di - адрес конца выводимого буфера (остальных букв)
     lea dx, sDownOut ;адрес строки 'Other letters:'
     lea bp, string ;адрес начала выводимой строки остальных букв
     call OutMessage ;выводим данные
    
     pop di  ;восстановим адрес конца в буфере заглавных букв
     call OutFile  ;выведем заглавные буквы в файл
    
    PressAny:
     lea dx, sAny ;выведем 'Press any key'
     mov ah, 9
     int 21h
    
     mov ah, 0  ; ждем нажатие на клавишу
     int 16h
    
     mov ax,4c00h ; конец работы
     int 21h
    main endp
    
    OutMessage proc  ;вывод строки с заголовком
     mov ah, 9  ;вывод заголовка, адрес в dx
     int 21h
    
     mov si, bp  ;адреса начала строки
     mov cx, di  ;адрес конца
     sub cx, si  ;длина строки
     mov ah, 2  ;функция вывода символа из dl
     jcxz NoMessage ;пустая строка?
    OutLoop:
     lodsb   ;символ
     mov dl, al  ;для вывода
     int 21h  ;выводим
     loop OutLoop  ;по всем cx символам
     ret
    NoMessage:   ;сообщение 'Not found'
     lea si, sNotFound ;начало строки
     mov cx, len_sNotFound;длина
     jmp OutLoop  ;на вывод
    OutMessage endp
    
    OutFile proc   ;вывод строки в файл
     lea dx, sName ;имя файла 'uppers.txt'
     xor cx, cx  ;без атрибутов
     mov ah, 3ch  ;создаем
     int 21h
     jc CreateError ;ошибка создания?
     mov bx, ax  ;описатель файла
    
     lea dx, uppers ;адрес строки заглавных букв
     mov cx, di  ;адрес конца
     sub cx, dx  ;длина
     jcxz NoUp  ;есть заглавные?
    Write:
     mov ah, 40h  ;выводим
     int 21h
     jc WriteError ;ошибка записи
    
     mov ah, 3eh  ;закрываем файл
     int 21h
     ret
    
    NoUp:    ;сообщение 'Not found'
     lea dx, sNotFound ;начало строки
     mov cx, len_sNotFound;длина
     jmp Write  ;на вывод
    
    WriteError:   ;ошибка записи
     mov ah, 3eh  ;файл закрываем
     int 21h
     lea dx, sWriteErr ;сообщение об ошибке
     jmp PrintError
    CreateError:   ;ошибка создания
     lea dx, sCreateErr ;сообщение об ошибке
    PrintError:
     mov ah, 9  ;выводим сообщение
     int 21h
     ret
    OutFile endp
    
     .data
    
    ;строки сообщений
    sIn  db 0dh,0ah,'Enter string:  $'
    sUpOut  db 0dh,0ah,'Upper-case letters: $'
    sDownOut db 0dh,0ah,'Other letters: $'
    sAny  db 0dh,0ah,'Press any key$'
    
    sName  db 'uppers.txt',0   ;имя файла
    sCreateErr db 0dh,0ah,'File create error!$'
    sWriteErr db 0dh,0ah,'File write error!$'
    sNotFound db 'Not found'   ;сообщение о ненахождении
    len_sNotFound equ $-sNotFound   ;длина сообщения
    
    buf label byte  ; буфер для приема строки с клавиатуры (по ф-и 0ah)
    max db 128  ; максимальная длина строки
    len db 0  ; реальная длина введенной строки
    string db 128 dup (?) ; сама строка
    
    uppers db 128 dup (?) ;сюда запишем заглавные буквы
    
     end main
    

    -----
    Люби своего ближнего, как самого себя

    Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
    Ответ отправлен: 16.06.2011, 13:03
    Номер ответа: 267754
    Украина, Кировоград
    Тел.: +380957525051
    ICQ # 234137952
    Mail.ru-агент: igorlyskov@mail.ru

    Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
    Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 267754 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:


  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.



    В избранное