Компьютерные порты
Слово «порт» в компьютере означает механизм, через который материнская плата (и процессор) обмениваются информацией с устройством. Сколько устройств, столько и портов.
Компьютер только тем и занимается, что откуда-то берёт информацию и куда-то её помещает. Например, берёт код нажатой буквы от клавиатуры (средство ввода – input) и помещает на экран (средство вывода – output).
Могут быть устройства, которые и получают информацию и передают её. Например данные на жёсткий диск или флэшку вначале записываются а потом (когда потребуется) считываются.
Я особо не работала с портами. Наверное потому, что так и не поняла что означает их адрес. Почти всё, что используется при работе хранится в оперативной памяти. У всего есть свои адреса.
Тут, например, показан вид памяти с адреса B800:0000:
http://akostina76.ucoz.ru/blog/2016-09-12-3431
В текстовом режиме именно этот кусок оперативной памяти отображается на экране. Если в этом куске напрямую что-то поменять, то при следующей отрисовке на экране появится что-то другое.
По адресу 0040:001E находится буфер клавиатуры:
http://assembler-src.blogspot.com/2010/04/blog-post_6094.html
Код нажатой кнопки появляется там. Его оттуда можно взять.
В начальных адресах хранятся ссылки на обработчики прерываний, т.е функции операционной системы, которые могут использовать программисты (вместо работы напрямую с аппаратным средствами компьютера).
А вот места, где хранится информация портов я так и не нашла. Могу предположить, что у материнской платы всё-таки есть своя память и тот байт с устройства, помещаемый или отправляемый в порт) хранится там. Даже если у компьютера 1000 портов – 1000 байт (букв) хранения информации это почти ничего.
Как бы то ни было, в ассемблере есть две функции для работы с портами. Это «inp [адрес]» - получить информацию от порта с адресом [адрес]. И «outp [адрес]» - записать информацию в порт с адресом [адрес].
Сразу оговорюсь, что монитор порта не имеет. В него информацию можно засунуть только через адрес в памяти. Оно и естественно. Обычный порт это то, чему хватает байта информации. А тут даже в текстовом режиме надо 80*40*2 байт (столбцов*строк*(буква+цвет)).
С самого начала было два стандартных порта. К LPT обычно подключался принтер. На этот порт можно только передавать информацию. Зачем нужно что-то получать от принтера? У него большой широкий разъем. Вот сколько штырьков:
Так, как описано тут:
http://www.hardline.ru/1/10/2308/
… я никогда не делала, потому утверждать, что будет так не возьмусь. Но возможно. Текст программы совсем простенький:
Option Explicit
Private Declare Function Inp Lib "inpout32.dll" _
Alias "Inp32" (ByVal PortAddress As Integer) As Integer
Private Declare Sub Out Lib "inpout32.dll" _
Alias "Out32" (ByVal PortAddress As Integer, ByVal Value As Integer)
Private Sub Command1_Click()
Out &H378, 15
End Sub
Тут подключается библиотека inpout32.dll, в которых есть функции вызывающие по одной ассемблерной команде (inp, outp) с конкретным адресом. Поскольку тут передача информации (outp) тут ещё и передаваемое число «15». Программа посылает в LPT порт число 15.
Чтобы увидеть настройки LPT порта надо запустить «Панель управления» А дальше Система->Оборудование->Диспетчер устройств. Вот он, этот LPT порт:
…и его шестнадцатеричный адрес ( «378h» – ассемблер, «0x378» - Си, «&H378» - VB)
Утверждается, что если прицепить к LPT такое:
… то разная информация будет зажигать разные светодиоды. В схеме переданный байт информации разделяется на отдельные 8 бит, т.е 8 проводников с информацией (на каждом 0 или 1, есть напряжение или нет). Сопротивление 200 Ом подтверждает, что напряжение тут 5 вольт. Ещё интереснее то, что это должно включить светодиоды или выключить. Т.е напряжение на отдельных проводниках будут сохраняться, пока не поменяется информация.
Порты типа COM изначально существовали для коммуникации (потому они и COM). Т.е они позволяют и принимать и получать информацию. Сделать сеть раньше было сложно. А переносить данные на дискетах долго. К тому же дискеты часто ломаются. Можно было соединить два компьютера через этот COM и перекинуть данные. Собственно, единственное, что я делала с портами это написала программу, которая печатала на экране второй машине то, что вводилось с клавиатуры первой. Т.е на одном компьютере всё, что билось на клавиатуре загонялось в COM-порт, а второй ловил эти байты, приходящие в порт и рисовал буквы на экране.
Жесткие диски доже работают через порты. Здесь:
https://www.experts-exchange.com/questions/10434239/Using-inp-outp-function.html
… пример получения информации с них. Кусок, позволяющий понять, как это происходит:
for (drive = 0; drive < 8; drive++) /* Loop through drives Вряд ли дисков больше чем 8 */
{
/* Get IDE Drive info */
switch (drive / 2)
{
case 0: base = 0x1f0; /* Адреса портов для работы с HD – жесткими дисками */
break;
case 1: base = 0x170; /* Разные но известные и фиксированные */
break;
case 2: base = 0x1e8;
break;
case 3: base = 0x168;
break;
}
/* Wait for controller not busy */
wait_loop = 100000;
/* Мгновенно и сразу не будет. Порт «зовут» 100 000 раз. Если не отозвался, то там ничего нет */
while (--wait_loop > 0)
{
in_val = inp (base + 7);
if (((in_val & 0x40) == 0x40) || ((in_val & 0x00) == 0x00))
break;
}
if (wait_loop < 1)
continue;
/* Если порт наконец ответил, то у него запрашивают определённую информацию, передавая что-то через outp */
outp (base + 6, ((drive % 2) == 0 ? 0xA0 : 0xB0)); /* Get Master/Slave drive */
outp (base + 7, 0xEC); /* Get drive info data */
/* Wait for data ready */
wait_loop = 100000;
/* Ответ запрашивают опять 100 000 раз */
while (--wait_loop > 0)
{
in_val = inp (base + 7);
if ((in_val & 0x48) == 0x48) /* drive ready and needs service */
break;
if ((in_val & 0x01) == 0x01) /* drive error */
break;
}
if ((wait_loop < 1) || ((in_val & 0x01) == 0x01)) /* Timed Out or Error */
continue;
А это ресурсы-адреса портов:
Два из трёх совпали. А третий не совпал возможно потому что ноутбук.
Ещё одно устройство, которое имеет смысл вспомнить это мышь, подключенная, например к ps/2:
https://marsohod.org/index.php/ourblog/11-blog/57-ps2proto
Первый байт в пакете передает знак перемещения SY и SX (вверх-вниз и влево-вправо), а так же состояние трех кнопок BM (middle - центральная), BR (right - правая), BL (left - левая):
1 0 SY SX 1 BM BR BL
Второй байт передает смещение по координате X.
X7 X6 X5 X4 X3 X2 X1 X0
Третий байт передает смещение по координате Y.
Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
Четвертый байт посылается только для мышей с колесом и только если оно включено. Определяет вращение колеса.
0 0 0 0 Z3 Z2 Z1 Z0
… Тут видна пакетная передача информация, т.е последовательно надо прочитать 4 переданных байта. С мышью всё просто. А сетевые протоколы, где больше требований к качеству и больше вероятность сбоя ещё и корректность всего что передано этими отдельными байтами проверяют. Но механизм тот же. Есть сетевой порт, в который (и из которого) по байту передаётся информация.
|