Скачиваний:
20
Добавлен:
16.05.2015
Размер:
58.9 Кб
Скачать

Министерство образования РФ

Брянский Государственный Технический Университет

Кафедра «Информатика и программное обеспечение»

Пояснительная записка

к курсовой работе по дисциплине

«Организация ЭВМ и систем»

на тему:

«Диагностика и конфигурирование последовательного порта передачи данных (com)»

Студент группы 11-ИВТ 1:

Даниличева С.О.

Преподаватель:

Конкин В.В

Брянск 2013г.

Оглавление

Введение…………………………………………………………………………...3

Введение 16

Ассемблерные программы могут быть очень эффективными. Из программистов, с равными навыками и способностями, работающий на языке ассемблера создаст программу более компактную и быстродействующую, чем такая же программа, написанная на языке высокого уровня. Это так практически для всех небольших или средних программ. К сожалению, по мере возрастания размеров, программы на языке ассемблера теряют часть своих преимуществ. Это происходит из-за необходимого в ассемблерной программе внимания к деталям. Язык ассемблера требует от программиста планирования каждого действия компьютера. В небольших программах это позволяет оптимизировать работу программы с аппаратными средствами. В больших же программах огромное количество деталей может помешать эффективно работать над самой программой, даже если отдельные компоненты программы окажутся очень неплохими. Безусловно, программирование на языке ассемблера отвечает потребностям не каждой программы. 16

Программы на языке ассемблера очень точны. Поскольку этот язык позволяет программисту непосредственно работать со всем аппаратным обеспечением, ассемблерная программа может делать то, что недоступно никакой другой программе. Несомненно, что в программировании устройств ввода-вывода, где требуется контроль над отдельными разрядами регистров устройства, программирование на языке ассемблера - единственный подходящий выбор. 16

Ясно, что эффективность и точность языка ассемблера дают определенные преимущества. Но его детализированность создает и некоторые проблемы. 16

Конечно, следует пользоваться программами на языке ассемблера, когда нет другого способа написать программу. Например, программисты фирмы IBM писали с использованием процедур ассемблера все программы управления устройствами ввода-вывода для IBM PC. Для управления устройствами ввода-вывода и системой прерываний, потребовалась та точность языка ассемблера которую не может обеспечить ни один другой язык программирования. Аналогично, на языке ассемблера в фирме IBM писались процедуры диагностики, которые должны проверять каждую деталь аппаратуры. 16

Язык ассемблера необходим также и в тех случаях, когда главными являются рабочие характеристики программы. Это может быть время исполнения или конечный размер программы. Конечно, на нем можно написать любую программу, однако с большой программой лучше работать в языке высокого уровня. Эти языки позволяют сосредоточиться на конкретной задаче и не приходится непосредственно иметь дело с тонкостями аппаратного оборудования и процессора. Языки высокого уровня «позволяют отступить назад и за деревьями увидеть лес». 16

1.Задание на программную разработку 17

2. СOM порт 18

2.1 COM-port: Ресурсы, конфигурирование, использование 19

3. Описание программы 24

3.1. Общий алгоритм работы программы 24

3.2. Структура данных программы 25

4. Листинг программы 26

.model small,c 26

.data 26

buf db 6,7 dup(0) ;принимает строку, введенную с клавиатуры 26

buf1 db 13,14 dup(0) ;принимает строку, введенную с клавиатуры 26

curdir db 80 dup(0) ;текущая директория 26

inp db 13,10,'Input file name: $' 26

msg db 13,10,'Input drive letter: $' 26

mainm db 'Главное меню',0 ;сообшение 26

mainm1 db '------------',0 ;сообщение 26

p1 db '1. О программе',0 ;пункт меню 26

p2 db '2. Старт программы',0 ;пункт меню 26

p3 db '3. Выход',0 ;пункт меню 26

sel db 'Выберите пункт меню:',0 ;сообщение 26

dno db 'Выбор пункта(Стрелка вверх - "", Стрелка вниз - ""). Подтверждение - <ENTER>',0 ;нижняя строка меню 26

conf db 'Действительно завершить программу?( <ENTER>-подтверждение, <ESC>-отказ):',0 ;подтверждение выхода 26

abmsg db ' ' 26

db ' ' 26

db ' ' 26

db ' Курсовая работа по ЭВМ ' 26

db ' ' 26

db ' ' 26

db ' Тема: "Дамп произвольного сектора устройства ' 26

db ' внешней памяти в формате HEX-Ascii в файл\на экран" ' 26

db ' ' 26

db ' ' 26

db ' ' 26

db ' ' 26

db ' ' 26

db ' ' 26

db ' ' 26

db ' Выполнил: ' 26

db ' студент гр. 11 - ИиВТ1 ' 26

db ' Свиридов В.А. ' 26

db ' Руководитель: ' 26

db ' доц. Конкин В.В. ' 26

db ' ' 26

db ' ' 26

db ' ' 26

db ' Брянск-2012 ' 26

db ' Для продолжения нажмите любую клавишу...$' 26

;структура для чтения сектора с диска 26

AbsDiskIORec dd 0 ;номер сектора 27

dw 1 ;количество читаемых секторов 27

dw sect ;смещение куда читать 27

dw @data ;сегмент 27

StartPath db ' :\',0 ;каталог 27

msg1 db 13,10,'Input logical sector number(0-$' 27

msg11 db '): $' 27

msg2 db 13,10,'Sector ',0 27

msg3 db 13,10,'Write in file (y/n): $' 27

msg4 db 13,10,'File created. $' 27

er db 13,10,'Error! Press any key to continue or Esc to exit...$' 27

crlf db 13,10,0 ;перевод строки 27

scr db 13,'Press any key to scroll',13,10,'$' 27

scrollcnt dw 2 ;количество выведенных на экран строк для скроллинга 27

sector dw 0 ;читаемый сектор 27

cc db 0 ;символ вывода в поток 27

sectsize dw 0 ;размер сектора 27

handle dw 1 ;хэндл выходного потока или файла 27

sect db 4096 dup (0) ;место под сектор 27

.stack 256 27

.code 27

start: 27

mov ax,@data ;Настраиваем сегментные регистры 27

mov ds,ax 27

mov ax,3 27

int 10h ;установить видеорежим 80*25 27

mov bp,1 ;номер выделенного пункта 27

mov ax,1000h 27

call cls ;очищаем экран 27

redraw_menu: 27

mov ah,1fh ;рисуем все надписи в меню 27

;там, где пишется mov dx,35*256+0 27

;первое число - это горизонтальная координата куда выводить текст, а второе - вертикальное, 27

;т.е mov dx,x*256+y 27

lea si,mainm 27

mov dx,35*256+0 27

call outtext1 27

lea si,mainm1 27

mov dx,35*256+1 27

call outtext1 27

lea si,p1 27

mov dx,25*256+9 27

call outtext1 27

lea si,p2 27

mov dx,25*256+11 27

call outtext1 27

lea si,p3 27

mov dx,25*256+13 27

call outtext1 27

lea si,sel 27

mov dx,20*256+17 27

call outtext1 27

lea si,dno 27

mov dx,1*256+24 27

call outtext1 27

cmp bp,1 ;если выделен 1-й пункт 27

jnz not1 27

mov dx,25*256+9 ;то подсветить его 27

not1: cmp bp,2 ;если выделен 2-й пункт 27

jnz not2 27

mov dx,25*256+11 ;то подсветить его 27

not2: cmp bp,3 ;если выделен 3-й пункт 27

jnz not3 27

mov dx,25*256+13 ;то подсветить его 27

not3: call highlight ;подсветить требуемый пункт меню 27

mov dx,41*256+17 27

mov ax,bp ;номер пункта 27

mov ah,1fh 27

add al,'0' ;преобразование в цифру 27

call printchar ;вывод номера пункта 27

mov ah,0 28

int 16h ;ожидание нажатия клавиши 28

cmp ah,48h ;если это "вверх" 28

jnz nvv 28

cmp bp,1 ;и не 1-й пункт 28

jz redraw_menu 28

dec bp ;то уменьшить номер пункта 28

jmp redraw_menu 28

nvv: cmp ah,50h ;если это "вниз" 28

jnz nvn 28

cmp bp,3 ;и не 3-й пункт 28

jz mm1 28

inc bp ;то увеличить номер пункта 28

mm1: jmp redraw_menu ;перерисовать меню 28

nvn: cmp al,13 ;если нажата клавиша Enter 28

jnz mm1 ;то в зависимости от пункта меню 28

cmp bp,1 ;вызывается соответствующая ветка программы 28

jz about 28

cmp bp,2 28

jz run 28

cmp bp,3 28

jz exit 28

jmp redraw_menu ;перерисовать меню 28

;О программе 28

about: mov ax,1f00h 28

call cls ;очистить экран 28

mov ah,9 ;вывести сообщение о программе 28

lea dx,abmsg 28

int 21h 28

mov ah,0 ;ожидаем нажатия любой клавиши 28

int 16h 28

jmp start ;возвращаемся в меню 28

;Выход 28

exit: mov ax,0c00h 28

call cls ;очистка экрана 28

mov dx,1*256+12 28

lea si,conf 28

mov ah,0ch 28

call outtext1 ;вывод вопроса с подтверждением 28

wt: mov ah,0 28

int 16h ;ожидание нажатия клавиши 28

cmp al,13 ;если enter 28

jz ex1 ;то выход 28

cmp al,1bh ;если не esc 28

jnz wt ;то продолжить ожидание 28

jmp start ;иначе вернуться в меню 28

ex1: mov ax,4c00h ;выход из порграммы 28

int 21h 28

;Запуск программы 28

run: mov ax,0f00h 28

call cls 28

mov ah,47h ;ф-я получения текущей директории 28

mov dl,0 ;текущий диск 28

lea si,curdir ;куда сохранять 28

int 21h ;получить текущую директорию 28

inp_bukv: 28

lea dx,msg ;выводимое сообщение 28

mov ah,9 ;ф-я вывода сообщения на экран 28

int 21h ;выводим сообщение на экран 28

mov ah,1 ;ф-я ввода символа с клавиатуры 28

int 21h ;ожидаем нажатия клавиши 28

mov StartPath,al ;сохранить ввебенную букву 28

mov ah,3bh ;ф-я смены директории 28

lea dx,StartPath ;корневая директория введенного диска 28

int 21h ;пробуем установить 28

jc inp_bukv ;если не установилась, значит диска нет, повторить 28

mov ah,3bh ;ф-я смены директории 28

lea dx,curdir ;старая директория 28

int 21h ;вернуться в старый подкаталог 28

28

mov ah,9 ;функция вывода сообщения на экран 29

lea dx,msg1 ;выводимое сообщение 29

int 21h ;выводим на экран 29

29

mov ah,36h ;ф-я определения параметров диска 29

mov dl,StartPath ;буква диска 29

and dl,0dfh ;сделать прописной 29

sub dl,'A' ;порядковый номер диска 29

inc dl ;номер диска 29

int 21h ;получить информацию о диске 29

mov ax,dx ;кол-во секторов на диске 29

call printdec ;вывести кол-во секторов 29

mov ah,9 ;функция вывода сообщения на экран 29

lea dx,msg11 ;выводимое сообщение 29

int 21h ;выводим на экран 29

29

mov ah,0ah ;ф-я ввода строки 29

lea dx,buf ;буфер куда вводить 29

int 21h ;вводим строку 29

lea si,buf[2] ;введенный текст 29

call str2dw ;преобразовываем в значение 29

mov sector,ax ;сохраняем номер головки 29

mov word ptr AbsDiskIORec,ax ;структура чтения сектра 29

mov al,StartPath ;буква диска 29

and al,0dfh ;сделать прописной 29

sub al,'A' ;порядковый номер диска 29

push ax ;сохранить регистры 29

push ds 29

mov ah,1ch ;функция, дающая информацию по диску 29

mov dl,al ;номер диска 29

inc dl ;для этой функции 29

int 21h ;Получить информацию 29

pop ds ;восстановить ds 29

mov sectsize,cx ;сохранить размер сектора 29

pop ax ;восстановить регистр 29

mov cx,0ffffh ;cx=ffff 29

xor dx,dx ;dx=0 29

lea bx,AbsDiskIORec ;адрес структуры 29

int 25h ;прочитать сектор 29

pop ax ;очистить стек 29

jnc m1 ;если нет ошибки - переход 29

err1: mov ah,9 ;функция вывода сообщения на экран 29

lea dx,er ;выводимое сообщение 29

int 21h ;выводим на экран 29

jmp ex2 ;выход 29

m1: call showsect ;вывести сектор на экран 29

m2: mov ah,9 ;функция вывода сообщения на экран 29

lea dx,msg3 ;выводимое сообщение 29

int 21h ;выводим на экран 29

mov ah,1 ;ф-я ввода символа с клавиатуры 29

int 21h ;ожидаем нажатия клавиши 29

and al,0dfh ;сделать прописной введенную букву 29

cmp al,'N' ;если нет 29

jz ex ;то закончить 29

cmp al,'Y' ;если не да 29

jnz m2 ;то вовторить ввод 29

mov ah,9 ;функция вывода сообщения на экран 29

lea dx,inp ;выводимое сообщение 29

int 21h ;выводим на экран 29

mov ah,0ah ;функция ввода строки с клавиатуры 29

mov dx,offset buf1 ;буфер куда вводить 29

int 21h ;пользователь вводит в текстовом виде в buf 29

mov bh,0 29

mov bl,buf1[1] ;длина введенной строки 29

mov buf1[bx+2],byte ptr 0;добавить 0 в конец введенной строки 29

mov ah,3ch ;функция открытия файла на чтение 29

mov cx,0 ;атрибуты файла 29

lea dx, buf1[2] ;введенное имя файла 30

int 21h ;создаем файл 30

jc err1 ;если ошибка - переход 30

mov handle,ax ;сохраняем хэндл, теперь вывод будет идти в файл 30

call showsect ;вывести сектор в файл 30

mov ah,3eh ;ф-я закрытия файла 30

mov bx,handle ;хэндл файла 30

int 21h ;закрыть файл 30

mov ah,9 ;функция вывода сообщения на экран 30

lea dx,msg4 ;выводимое сообщение 30

int 21h ;выводим на экран 30

ex2: mov ah,0 30

int 16h ;ожидаем нажатия любой клавиши 30

ex: mov ax,4c00h ;закончить программу 30

int 21h 30

showsect proc 30

call puts,offset msg2 ;вывести сектор 30

mov ax,sector ;и его 30

call printdec ;номер 30

lea si,sect ;адрес начала сектора 30

mov bx,0 ;смещение относительно начала сектора 30

mov dx,sectsize ;размер сектора 30

mov cl,4 30

shr dx,cl ;делим на 16 = количество строк 30

m12: call puts,offset crlf ;перевод строки 30

mov al,bh ;старшая часть смещения 30

call printhex ;выводим на экран 30

mov al,bl ;младшая часть смещения 30

call printhex ;выводим на экран 30

mov al,' ' ;пробел 30

call putc ;выводим два пробела 30

call putc 30

mov cx,16 ;количество байт в строке 30

m13: mov al,[bx+si] ;берем очередной байт 30

call printhex ;и выводим на экран 30

mov al,' ' ;пробел 30

call putc ;выводим два пробела 30

inc bx ;следующий байт 30

loop m13 ;выводим всю строку 30

;вывод в символьном виде 30

mov al,' ' ;пробел 30

call putc ;выводим два пробела 30

call putc 30

sub bx,16 ;смещение начала строки 30

mov cx,16 ;количество байт в строке 30

m113: mov al,[bx+si] ;берем очередной байт 30

cmp al,13 ;если в правой части дампа 30

jz pc1 ;при выводе 30

cmp al,7 ;встречаются 30

jz pc1 ;служебные 30

cmp al,8 ;символы 30

jz pc1 ;с кодами 7-10,13 30

cmp al,9 ;то 30

jz pc1 ;вместо них 30

cmp al,10 ;вывести 30

jz pc1 ;точку 30

pc2: call putc ;и выводим на экран символ 30

inc bx ;следующий байт 30

loop m113 ;выводим всю строку 30

dec dx ;уменьшаем количество строк 30

jnz m12 ;продолжаем пока не останется 0 30

ret 30

pc1: mov al,'.' ;заменить служебный символ точкой 30

jmp pc2 ;и вывести 30

showsect endp 30

str2dw proc 30

;Преобразование строки в число 30

;на входе ds:si ссылается на ASCII строку, которую нужно преобразовать 31

;на выходе в ax - число. 31

push dx ;сохраняем регистры 31

push si 31

xor dx,dx ;сумма 31

@lp1: xor ax,ax 31

lodsb ;берем символ 31

cmp al,13 ;если это конец строки, 31

jz @ex ;то заканчиваем 31

cmp al,'9' ;если это не цифра, 31

jnbe @lp1 ;то пропускаем 31

cmp al,'0' ;если это не цифра, 31

jb @lp1 ;то пропускаем 31

sub ax,'0' ;получаем цифровое значение 31

shl dx,1 ;умножаем сумму на 10 31

add ax, dx 31

shl dx, 2 31

add dx, ax ;прибавляем текущее значение 31

jmp @lp1 ;продолжаем обработку 31

@ex: mov ax,dx ;помещаем результат в ах 31

pop si ;восстанавливаем регистры 31

pop dx 31

ret ;выход их подпрограммы 31

str2dw endp 31

;------------------------------------------------------------------------------------------- 31

;преобразование числа из ах в десятичную строку и вывод на экран 31

;ax - число 31

printdec proc 31

push cx ;сохраняем регистры 31

push dx 31

push bx 31

mov bx,10 ;основание системы 31

xor cx,cx ;в сх будет количество цифр в десятичном числе 31

@@m1a: xor dx,dx 31

div bx ;делим число на степени 10 31

push dx ;и сохраняем остаток от деления(коэффициенты при степенях) в стек 31

inc cx ;увеличиваем количество десятичных цифр числа 31

test ax,ax ;после деления остался 0? 31

jnz @@m1a ;если нет, продолжаем 31

@@m2a: pop ax ;взять из стека цифру цисла 31

add al,'0' ;преобразовываем цифру в ASCII символ 31

call putc ;вывести на экран 31

loop @@m2a ;все цифры 31

pop bx ;восстанавливаем регистры 31

pop dx 31

pop cx 31

ret ;выход из подпрограммы 31

printdec endp 31

;Печать 16-разрядного 16-ричного числа 31

;На входе: AX - число 31

printhex16 proc 31

push ax ;сохранить параметр 31

mov al,ah 31

call printhex ;вывести старшую часть 31

pop ax ;восстановить параметр 31

call printhex ;вывести младшую часть 31

ret ;выход из подпрограммы 31

printhex16 endp 31

printhex proc 31

;преобразование байта в текстовый вид и вывод на экран 31

;al - байт; 31

push dx ;сохраняем регистры 31

push ax 31

push ax ;сохраняем значение 31

shr al,4 ;сдвигаем выводимый код на 4 бита вправо 31

add al,'0' ;преобразуем старшую(левую)тетраду в символ 31

cmp al,'9' ;если не это буква A-F 31

jbe @m1 ;то пропускаем 31

add al,7 ;а если буква,то корректируем символ 31

@m1: call putc ;выводим ее на экран 32

pop ax ;восстанавливаем значение 32

and al,0fh ;выделяем младшую тетраду 32

add al,'0' ;преобразуем старшую(левую)тетраду в символ 32

cmp al,'9' ;если не это буква A-F 32

jbe @m2 ;то пропускаем 32

add al,7 ;а если буква,то корректируем символ 32

@m2: call putc ;выводим ее на экран 32

pop ax ;восстанавливаем регистры 32

pop dx 32

ret ;выход из подпрограммы 32

printhex endp 32

;вывод символа на консоль или в файл 32

;al - выводимый символ 32

putc proc 32

push ax 32

push cx ;сохранить регистры 32

push bx 32

push dx 32

push ds 32

mov cc,al ;сохраняем символ 32

mov bx,handle ;хэндл выводимого устройства (файл или экран) 32

mov ah,40h ;ф-я записи 32

mov cx,1 ;1 символ 32

lea dx,cc ;его адрес 32

int 21h ;выводим символ 32

cmp cc,10 ;если это не перевод строки 32

jnz pl3 ;то пропустить 32

inc scrollcnt ;увеличить количество выведенных строк 32

cmp handle,1 ;если выводим не на экран 32

jnz pl3 ;то пропустить 32

mov ax,scrollcnt;кол-во выведенных строк 32

xor dx,dx ;подготовить деление 32

mov cx,23 ;количество строк после которого ожидать скроллинг 32

div cx ;scrollcnt/23 32

test dx,dx ;проверить остаток от деления 32

jnz pl3 ;если не 0, пропустить 32

mov ah,9 ;функция вывода сообщения на экран 32

lea dx,scr ;выводимое сообщение 32

int 21h ;выводим на экран 32

mov ah,8 ;ф-я ожидания нажатия клавиши 32

int 21h ;ожидаем выбор пользователя 32

32

32

pl3: pop ds ;восстанавливаем регистры 32

pop dx 32

pop bx 32

pop cx 32

pop ax 32

ret 32

putc endp 32

;вывод строки на экран 32

puts proc string:word 32

push si ;сохранить регистр 32

mov si,string ;выводимая строка 32

pl1: mov al,[si] ;взять символ 32

cmp al,0 ;если 0 32

jz pl2 ;то закончить 32

call putc ;вывести очередной символ 32

inc si ;следующий символ 32

jmp pl1 ;вывести всю строку 32

pl2: pop si ;восстановить регистр 32

ret 32

puts endp 33

;очистка экрана 33

cls: push 0b800h 33

pop es ;es настроен на видеопамять 33

xor di,di ;начало видеопамяти 33

mov cx,2000 ;кол-во символов на экране 33

rep stosw ;Очистить экран 33

mov ah,2 ;ф-я установки позиции курсора 33

xor dx,dx ;верхний левый угол 33

mov bh,0 33

int 10h ;установить крсор в верхний левый угол 33

ret 33

printchar proc ;процедура вывода символа на экран 33

; al - символ;ah-атрибуты 33

;dh - x 33

;dl - y 33

push es ;сохраняем регистры 33

push bx 33

push dx 33

push 0b800h ;настраиваем сегментный регистр на видеопамять 33

pop es 33

push dx 33

xor dh,dh ;смещение в экранном сегменте расчитывается так: dl(y)*80(кол-во столбцов)*2(два байта на символ) + dh(x)*2(два байта на символ) 33

shl dx,5 33

mov bx,dx 33

shl dx,2 33

add bx,dx ;y*160 33

pop dx 33

mov dl,dh 33

xor dh,dh 33

shl dx,1 ;x*2 33

add bx,dx ;окончательно расчитываем адрес символа в видеопамяти 33

mov es:[bx],ax ;выводим на экран(прямо в экранную память) 33

pop dx ;восстанавливаем регистры 33

pop bx 33

pop es 33

ret 33

printchar endp 33

getchar proc ;процедура чтения символа с экрана 33

;dh - x 33

;dl - y 33

;возвращает: 33

; al - символ;ah-атрибуты 33

push es ;сохраняем регистры 33

push bx 33

push dx 33

push 0b800h ;настраиваем сегментный регистр на видеопамять 33

pop es 33

push dx 33

xor dh,dh ;смещение в экранном сегменте расчитывается так: dl(y)*80(кол-во столбцов)*2(два байта на символ) + dh(x)*2(два байта на символ) 33

shl dx,5 33

mov bx,dx 33

shl dx,2 33

add bx,dx ;y*160 33

pop dx 33

mov dl,dh 33

xor dh,dh 33

shl dx,1 ;x*2 33

add bx,dx ;окончательно расчитываем адрес символа в видеопамяти 33

mov ax,es:[bx] ;выводим на экран(прямо в экранную память) 33

pop dx ;восстанавливаем регистры 33

pop bx 33

pop es 33

ret 33

getchar endp 33

;вывод текста 34

;в si адрес ASIIZ-строки 34

;dh - x 34

;dl - y 34

;ah - цвет 34

outtext1: 34

olp: mov al,[si] 34

test al,al 34

jz oex 34

cmp al,13 34

jnz not13 34

mov dh,0 34

jmp oo1 34

not13: cmp al,10 34

jnz not10 34

inc dl 34

jmp oo1 34

not10: call printchar 34

inc dh 34

oo1: inc si 34

jmp olp 34

oex: ret 34

;Подсветска пункта меню 34

highlight: 34

hlp: call getchar ;берем символ с экрана 34

test al,al ;если это 0 34

jz hex ;то закончить подсвечивание 34

mov ah,7fh ;меняем атрибуты 34

call printchar ;и выводим символ на то же место 34

inc dh 34

jmp hlp 34

hex: ret 34

end start 34

5. Описание функционального состава разработанной программы 35

6. Инструкция пользователя 36

7. Заключение 37

8.Список использованной литературы 38

Соседние файлы в папке Курсовая работа - Диагностика и конфигурирование последовательного порта передачи данных (com)