Интерфейсы. Общие положения.

Толковый словарь по вычислительным системам определяет понятие интерфейс (interface) как границу раздела двух систем, устройств или программ; элементы соединения и вспомогательные схемы управления, используемые для соединения устройств. Интерфейсы, позволяют подключать к компьютерам разнообразные периферийные устройства (ПУ) и их контроллеры, а также соединять отдельные подсистемы компьютера. Рассмотрим вкратце основные свойства интерфейсов.

clip_image001

По способу передачи информации интерфейсы подразделяются на параллельные и последовательные. В параллельном интерфейсе все биты передаваемого слова (обычно байта) выставляются и передаются по соответствующим параллельно идущим проводам одновременно. В PC традиционно используется параллельный интерфейс Centronics, реализуемый LPT-портами, шины ATA, SCSI и все шины расширения. В последовательном интерфейсе биты передаются друг за другом, обычно по одной (возможно, и двухпроводной) линии. Эта линия может быть как однонаправленной (например, в RS-232C, реализуемой СОМ-портом, шине FireWire, SPI, JTAG), так и двунаправленной (USB, PC).

При рассмотрении интерфейсов важным параметром является пропускная способ­ность. Технический прогресс приводит к неуклонному росту объемов передаваемой информации. Если раньше матричные принтеры, печатающие в символьном режи­ме, могли обходиться и СОМ-портом с невысокой пропускной способностью, то современным лазерным принтерам при высоком разрешении не хватает произво­дительности даже самых быстрых LPT-портов. То же касается и сканеров. А пере­дача «живого» видео, даже с применением компрессии, требует ранее немысли­мой пропускной способности.

Вполне очевидно, что при одинаковом быстродействии приемопередающих цепей и пропускной способности соединительных линий по скорости передачи параллель­ный интерфейс должен превосходить последовательный. Однако повышение про­изводительности за счет увеличения тактовой частоты передачи данных упирается в волновые свойства соединительных кабелей. В случае параллельного интерфей­са начинают сказываться задержки сигналов при их прохождении по линиям ка­беля и, что самое неприятное, задержки в разных линиях интерфейса могут быть различными вследствие неидентичности проводов и контактов разъемов. Для на­дежной передачи данных временные диаграммы обмена строятся с учетом возмож­ного разброса времени прохождения сигналов, что является одним из факторов, сдерживающих рост пропускной способности параллельных интерфейсов. В по­следовательных интерфейсах, конечно же, есть свои проблемы повышения произ­водительности, но поскольку в них используется меньшее число линий (в преде­ле — одна), повышение пропускной способности линий связи обходится дешевле.

Для повышения пропускной способности параллельных интерфейсов с середин 90-х годов стали применять двойную синхронизацию DDK (Dual Data Rate). Eё идея заключается в выравнивании частот переключения информационных cигнальных линий и линий стробирования (синхронизации). В «классическом» варианте данные информационных линий воспринимались только по одному перепаду (фронту или спаду) синхросигнала, что удваивает частоту переключена линии синхросигнала относительно линий данных. При двойной синхронизаци данные воспринимаются и по фронту, и по спаду, так что частота смены состояний всех линий выравнивается, что при одних и тех же физических параметра кабеля и интерфейсных схем позволяет удвоить пропускную способность. Волна этих модернизаций началась с интерфейса АТА (режимы UltraDMA) и прошл уже и по SCSI (UltralGO и выше), и по памяти (DDK SDRAM), и по системно! шине процессоров (Pentium 4).

Немаловажен для интерфейса контроль достоверности передачи данных, который, увы, имеется далеко не везде. «Ветераном» контроля является шина SCSI с ее битом паритета; контроль паритета применяется и в последовательных интерфейсах и в шине PCI. Шина ISA в этом плане беззащитна, как и ее «потомок» — интер­фейс АТА, в котором до UltraDMA контроля достоверности не было. В новых интерфейсах контролю достоверности уделяется серьезное внимание, поскольку они, как правило, рассчитываются на экстремальные условия работы (высокие частоты, большие расстояния и помехи). Контроль достоверности может произ­водиться и на более высоких протокольных уровнях (контроль целостности паке­тов и их полей), но на аппаратном уровне он работает, естественно, быстрее.

clip_image002

Для интерфейса, соединяющего (физически или логически) два устройства, раз­личают три возможных режима обмена — дуплексный, полудуплексный и симп­лексный. Дуплексный режим позволяет по одному каналу связи одновременно передавать информацию в обоих направлениях. Он может быть асимметричным, если значения пропускной способности в направлениях «туда» и «обратно» суще­ственно различаются, или симметричным. Полудуплексный режим позволяет пере­давать информацию «туда» и «обратно» поочередно, при этом интерфейс имеет средства переключения направления канала. Симплексный (односторонний) ре­жим предусматривает только одно направление передачи информации (во встреч­ном направлении передаются только вспомогательные сигналы интерфейса).

Другим немаловажным параметром интерфейса является допустимое удаление соединяемых устройств. Оно ограничивается как частотными свойствами кабелей, так и помехозащищенностью интерфейсов. Часть помех возникает от соседних ли­ний интерфейса — это перекрестные помехи, защитой от которых может быть применение витых пар проводов для каждой линии. Другая часть помех вызыва­ется искажением уровней сигналов.

С появлением шин USB и Fire Wire в качестве характеристики интерфейса стала фигурировать и топология соединения. Для интерфейсов RS-232C и Centronics практически всегда применялась двухточечная топология PC — устройство (или PC — PC). Исключениями из этого правила являются различные устройства безопасности и защиты данных (Security devices), которые подключаются к СОМ- или LPT-портам, но имеют разъем для подключения внешнего устройства. Однако эти устройства для традиционной периферии прозрачны, поэтому можно считать, что они не нарушают общего правила. Аналогично обстоит дело и с адаптерами ло­кальных сетей (например, Paraport) и внешних дисковых накопителей (Iomega Zip), подключаемых к LPT-портам. Хотя разрабатываемые стандарты для парал­лельного порта (IEEE 1284.3) и предусматривают соединение устройств в цепоч­ку (Daisy Chain) или через мультиплексоры, широкого распространения такие способы подключения пока не получили. К другому классу исключений относится построение моноканала на СОМ-портах, которое несколько лет назад применялось в «любительских» локальных сетях, но было вытеснено существенно более эффек­тивной и подешевевшей технологией Ethernet. Интерфейсные шины USB и Fire Wire реализуют древовидную топологию, в которой внешние устройства могут быть как оконечными, так и промежуточными (разветвителями). Эта топология позволяет подключать множество устройств к одному порту USB или Fire Wire.

Важным свойством интерфейса, на которое часто не обращают внимание, являет­ся гальваническая развязка, а точнее — ее отсутствие.« Схемные земли» устройств, соединяемых интерфейсом с СОМ- или LPT-портом PC, оказываются связанны­ми со схемной землей компьютера (а через интерфейсный кабель и между собой). Если между ними до подключения интерфейса была разность потенциалов, то по общему проводу интерфейса потечет уравнивающий ток, что плохо по целому ряду причин. Падение напряжения на общем проводе, вызванное протеканием этого тока, приводит к смещению уровней сигналов, а протекание переменного тока приводит к сложению полезного сигнала с переменной составляющей поме­хи. К этим помехам особенно чувствительны ТТЛ-интерфейсы; в то же время в RS-232C смещение и помеху в пределах 2 В поглотит зона нечувствительности. В случае обрыва общего провода или плохого контакта, а гораздо чаще — при под­ключении и отключении интерфейсов без выключения питания устройств, раз­ность потенциалов прикладывается к сигнальным цепям, а протекание уравни­вающих токов через них часто приводит к пиротехническим эффектам. Гальваническую развязку устройств обеспечива­ют интерфейсы MIDI, «токовая петля», S/PDIF, шина FireWire, сетевые интерфейсы Ethernet.

Существенным свойством является возможность «горячего» подключения/отклю­чения или замены устройств (Hot Swap), причем в двух аспектах. Во-первых, это безопасность переключений «на ходу» как для самих устройств и их интерфейс­ных схем, так и для целостности хранящихся и передаваемых данных и, наконец, для человека. Во-вторых, это возможность использования вновь подключенных устройств без перезагрузки системы, а также продолжения устойчивой работы системы при отключении устройств. Далеко не все внешние интерфейсы поддер­живают «горячее подключение» в полном объеме, так, например, зачастую сканер с интерфейсом SCSI должен быть подключен к компьютеру и включен до загруз­ки ОС, иначе он не будет доступен системе. С новыми шинами USB и FireWire проблем «горячего подключения» не возникает. Для внутренних интерфейсов «горячее подключение» несвойственно. Это касается и шин расширения, и модулей памяти, и даже большинства дисков АТА и SCSI. «Горячее подключение» под­держивается для шин расширения промышленных компьютеров, а также в специ­альных конструкциях массивов устройств хранения.

В ряде интерфейсов заложены возможности PnP (Plug and Play — включай и играй), которые предназначены для снятия с пользователей забот по конфигурированию подключаемых устройств. В современных интерфейсах эти возможности заклады­вались изначально (PCI, USB, Fire Wire, Bluetooth), и эти функции в большинстве случаев работают нормально. Однако для интерфейсов-ветеранов (например, ISA, SCSI) технология PnP является поздней искусственной надстройкой, работающей с переменным успехом (Plug and Pray — включай и молись). Часто побочные эффек­ты вызваны наследием «тяжелого прошлого» — соседством устройств РпР с тради­ционными (legacy) устройствами. На закате шины ISA ее система РпР в общем работала, но в SCSI от идей автоконфигурирования со временем отказались.

При разработке собственных устройств встает вопрос выбора подходящего интер­фейса подключения. Этот вопрос следует решать, исходя из принципа разумной достаточности, по возможности отдавая предпочтение внешним интерфейсам. Следует помнить, что разработка аппаратной части устройства (hardware) тесно связана и с программной поддержкой устройств — как модулями ПО, исполня­емыми процессором компьютера (software), так и программами встроенного мик­роконтроллера (firmware), на базе которого, как правило, строятся современные устройства. Промышленностью выпускается множество моделей микроконтрол­леров, имеющих популярные интерфейсы (USB, RS-232, PC и другие). Однако в ряде случаев приходится использовать и стандартизованные шины расширения ввода-вывода. Эти шины предоставляют более широкие возможности для взаи­модействия процессора с аппаратурой, нескованные жесткими ограничениями внешних интерфейсов. Однако за универсальность и производительность внут­ренних шин расширения приходится расплачиваться более замысловатой реали­зацией интерфейсных схем и сложностями при обеспечении совместимости с дру­гим установленным в компьютер оборудованием. Здесь ошибки могут приводить к потере работоспособности компьютера. Недаром серь­езные производители компьютеров гарантируют работоспособность своих изделий только при установке сертифицированных карт расширения. При использовании внешних интерфейсов неприятности в случае ошибок чаще всего имеют отношение только к подключаемому устройству.

Определение системных ресурсов ПЭВМ

Цель работы: изучение и использование функций BIOS и DOS, системных данных и таблиц для решения задачи определения состава, типов и параметров присоединенного оборудования и некоторых других системных ресурсов и данных ПЭВМ:

1. типа персонального компьютера;

2. размера основной и дополнительной памяти;

3. даты изготовления базовой системы ввода/вывода;

4. числа и типов накопителей на магнитных дисках;

5. типа и параметров видеосистемы;

6. типов и числа других периферийных устройств;

7. номера версии установленной операционной системы.

Краткие теоретические сведения:

Для решения указанных задач предлагается составить программу на языке Turbo Pascal с использованием его расширенных возможностей, таких как : размещение переменных по абсолютным адресам памяти, непосредственный доступ к ячейкам памяти и портам, организация программных прерываний и системных вызовов, программирование на низком уровне. Кратко рассмотрим эти возможности Turbo Pascal. В Turbo Pascal имеются средства размещения переменных по конкретным адресам оперативной памяти. Такие переменные называются абсолютными. Для описания абсолютных переменных предназначено зарезервированное слово Absolute. Формат описания переменных этого типа выглядит так :

Var <идентификатор> : <тип> Absolute BA:BS;

Здесь BA:BS - абсолютный адрес ячейки оперативной памяти (байта памяти), начиная с которой отводится место для хранения значения переменной <идентификатор> указанного типа <тип>;

BA - базовый адрес сегмента; BS - смещение внутри этого сегмента.

Для работы с абсолютными переменными (определения абсолютных адресов переменных, записи и считывания информации из конкретных ячеек памяти) в Turbo Pascal имеется ряд стандартных подпрограмм : Addr, CSeg, DSeg, Ofs, Ptr, Seg, SSeg.

В Turbo Pascal определены пять предварительно объявленных массивов : Mem, MemW, MemL, Port и PortW. Первые три массива обеспечивают непосредственный доступ (запись и чтение) к любому участку памяти по абсолютному адресу, два других массива - доступ к портам ввода/вывода.

Для осуществления работы с регистрами процессора ПЭВМ, организации программных прерываний, использования большинства возможностей операционной системы MS-DOS предназначен системный модуль DOS Turbo Pascal.

Реализация всех этих возможностей практически всегда предполагает обращение к регистрам центрального процессора.

Для этих целей в модуле DOS определен специальный тип данных Registers :

Type Registers = Record

Case Integer of 0 : (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : Word);

1 : (AL, AH, BL, BH, CL, CH, DL, DH : Byte)

End;

Этот тип имитирует набор регистров центрального процессора и предоставляет возможность обращаться к ним как к переменным типа Word, а для первых четырех регистров разрешено работать с их младшими и старшими байтами независимо, как с байтовыми переменными.

Для организации программных прерываний и выполнения системных функций MS-DOS в модуле DOS Turbo Pascal имеются две стандартные процедуры Intr и MsDos.

Первая процедура Intr инициирует программное прерывание с требуемым номером:

Intr(Num_Int : Byte; var Regs : Registers);

Здесь : Num_Int - номер программного прерывания, которое не обходимо вызвать (0..255);

Regs - запись, в которой процедуре обработки прерывания с номером Num_Int передаётся содержимое регистров и в ней же возвращается выходная информация.

Язык Turbo Pascal допускает три основные возможности для использования средств программирования на низком уровне (язык машинных команд и фрагменты на языке Ассемблера) :

1. Можно написать одну или несколько процедур на языке Ассемблера (вне среды Turbo Pascal), оттранслировать их, получив объектные модули этих процедур, и затем подключить эти модули к Pascal-программе. Для этого в Turbo Pascal существует служебное слово External, указываемое в заголовке процедуры, и директива компилятора $L.

2. Turbo Pascal позволяет непосредственно включать в текст программы фрагменты, написанные на машинном коде. Это достигается использованием inline-операторов и inline-процедур.

3. Начиная с шестой версии Turbo Pascal появилась возможность включения в текст Pascal-программы фрагментов на языке Ассемблера. Средства, поддерживающие эту возможность, называют "встроенный Ассемблер".

ТЕКСТ ПРОГРАММЫ:

program xyz;

uses crt,dos,art,PRINTER;

type zapis=record

OS_Pam,DOP_PAm,Video_Pam:word;

Tip_Kompa,data_biosa:string[20];

NZMD,GMDA,GMDB,Displai,so_proch,igr,_print,MSDOS:string;

posled_port,paral_port:integer;

end;

var st:array [1..4] of string;

ch:integer;

My:zapis;

function type_Pc:string;

var s:byte absolute $F000:$FFFE;

begin

case s of

$FF:type_Pc:='Тип компьютера IBM PC';

$FD:type_Pc:=' Тип компьютера IBM PCjr';

$FE:type_Pc:= Тип компьютера IBM PC/XT';

$FC:type_Pc:=' Тип компьютера IBM PC/AT';

end;

end;

function MS_DOS:string;

var Regs:Registers;

s1,s2:string;

begin

Regs.AH:=$30;

MsDos(Regs);

str(Regs.AL,s1);str(Regs.AH,s2);

MS_DOS:='Версия MS-DOS '+s1+'.'+s2;

end;

procedure SIZE_MEM(var os:word;var dp:word;var video:word);

var Regs:Registers;

begin

os:=memw[$0000:$0413];

Intr($15,Regs);

dp:=Regs.AX;

video:=memw[$40:$4C];

end;

function Date_Bios:string;

var i:integer;

stroka:string;

W:byte;

begin

stroka:='';

write('Дата создания биоса ');w:=$0004;

for i:=1 to 8 do

begin

w:=w+1;

stroka:=stroka+chr(mem[$ffff:w]);

end;

Date_Bios:=stroka;

end;

function video_sys:string;

var regs:Registers;

begin

Regs.AH:=$1A;Regs.AL:=$00;

intr($10,regs);

case Regs.BL of

$00:video_sys:='Монохромный дисплей';

$01:video_sys:='Монохромний адаптер - Монохромный дисплей';

$02:video_sys:='Адаптер CGA-цветной дисплей';

$04:video_sys:='Адаптер EGA-цветной дисплей';

$05:video_sys:='Адаптер EGA-монохромный дисплей';

$07:video_sys:='Адаптер VGA-монохромный аналоговый дисплей';

$08:video_sys:='Адаптер VGA- цветной аналоговый дисплей';

$0A:video_sys:='Адаптер VGA- цветной цифровой дисплей';

end;

end;

function Kol_GMD(var s:string):string;

var i:integer;

k:byte;

begin

for i:=1 to 2 do

begin

port[$70]:=$10;

k:=port[$71];

if i=1 then k:=k shr 4 else k:=k shl 4;

case k of

0:s:='Дисковода нет или его тип не известен';

1:s:=' на 360 Kb, для дискет диаметром 5.25';

2:s:=' на 1.2 Mb, для дискет диаметром 5.25';

3:s:=' на 720 Kb, для дискет диаметром 3.5';

4:s:=' на 1.44 Mb, для дискет диаметром 3.5';

5:s:=' на 2.88 Mb, для дискет диаметром 3.5';

6:s:=' не установлен’;

end;

if i=1 then Kol_GMD:=s;

end;

end;

function kol_ZMD:string;

var k:byte;

s:string;

begin

k:=mem[$45:$75];

str(k,s);

kol_ZMD:='Колличество жеских магнитных дисков-'+s;

end;

function soproch:string;

var k:word;

begin

k:=memw[$40:$10] and 2;

k:=k shr 1;

if k=1 then soproch:='есть математический сопроцессор'

else soproch:=' математический сопроцессор отсутсвует';

end;

function igr_adap:string;

var k:word;

begin

k:=memw[$40:$10] and 4096;

k:=k shr 13;

if k=1 then igr_adap:='есть игровой адаптер '

else igr_adap:='игровой адаптер отсутсвует';

end;

function Kol_posled_port:integer;

var k:word;

begin

k:=memw[$40:$10];

k:=k shl 4;k:=k shr 13;

Kol_posled_port:=k;

end;

function Kol_paral_port:integer;

var k:word;

begin

k:=memw[$40:$10];

k:=k shr 14;

Kol_paral_port:=k;

end;

function print:string;

var k:word;

begin

k:=memw[$40:$10] and 4096;

k:=k shr 14;

if k=1 then print:='установлен последовательный принтер'

else print:=' последовательный принтер не установлен’;

end;

procedure zopolnenie;

begin

with my do

begin

tip_kompa:=type_pc;

size_mem(os_pam,dop_pam,video_pam);

data_biosa:=Date_Bios;

GMDA:=Kol_GMD(GMDB);

displai:=video_sys;

NZMD:=kol_ZMD;

so_proch:=soproch;

igr:=igr_adap;

_print:=print;

posled_port:=Kol_posled_port;

paral_port:=Kol_paral_port;

MSDOS:=MS_DOS;

end;

end;

procedure vivod_disp;

begin

clrscr;

with my do

begin

textcolor(2);writeln(' ОБЩИЕ СВЕДЕНИЯ'); textcolor(7);

writeln(tip_kompa);writeln(MSDOS);

writeln('Дата создания BIOSa-',data_biosa);

textcolor(2);Writeln(' ПАМЯТЬ ');textcolor(7);

writeln('Колличество основной памяти (Kб)-',os_pam);

writeln('Колличество дополнительной памяти(Kб)-',dop_pam);

writeln('Память видео страницы(байт)-',video_pam);

textcolor(2);writeln(' ДИСКИ');textcolor(7);

writeln('Дисковод A:',GMDA);

writeln('Дисковод B:',GMDB);

writeln(NZMD);

textcolor(2);writeln(' ВИДЕО');textcolor(7);

writeln(displai);

textcolor(2);writeln(' ДОПОЛНИТЕЛЬНЫЕ СВЕДЕНИЯ');textcolor(7);

writeln(so_proch);

writeln(igr);

writeln(_print);

writeln('Колличество последовательных портов -',posled_port);

writeln(' Колличество паралельных портов -',paral_port);

end;

end;

procedure vivod_fail;

var f:text;

s:string;

begin

clrscr;

write('Введите путь к файлу -');readln(s);

assign(f,s);rewrite(f);

with my do

begin

writeln(f,' ОБЩИЕ СВЕДЕНИЯ');

writeln(f,tip_kompa);writeln(f,MSDOS);

writeln(f,'Дата создания BIOSa-',data_biosa);

Writeln(f,' ПАМЯТЬ');

writeln(f,'Колличество основной памяти (Kб)-',os_pam);

writeln(f,'Колличество дополнительной памяти (Kб)-',dop_pam);

writeln(f,'Память видео страницы (байт)-',video_pam);

writeln(f,' ДИСКИ');

writeln(f,'Дисковод A:',GMDA);

writeln(f,'Дисковод B:',GMDB);

writeln(f,NZMD);

writeln(f,' ВИДЕО');

writeln(f,displai);

writeln(f,' ДОПОЛНИТЕЛЬНЫЕ СВЕДЕНИЯ ');

writeln(f,so_proch);

writeln(f,igr);

writeln(f,_print);

writeln(f,'Колличество последовательных портов -',posled_port);

writeln(f,' Колличество паралельных портов -',paral_port);

end;

close(f);

end;

procedure vivod_print;

var Lst:text;

s:string;

begin

clrscr;

write('Введите путь к файлу -');readln(s);

assign(Lst,s);reset(lst);

while not eof(Lst) do

begin

readln(Lst,s);

writeln(Lst,s);

end;

close(Lst);

end;

BEGIN

clrscr;

st[1]:='Вивод информации на дисплей';st[2]:='Вывод информации в файл';

st[3]:='Вывод информации на принтер';st[4]:='Выход';

zopolnenie;

repeat

ch:=menu_s(st,4,0,0);

case ch of

1:begin vivod_disp;readln;end;

2:vivod_fail;

3:vivod_print;

end;

until ch=4 ;

END.

РЕЗУЛЬТАТЫ РАБОТЫ ПРОГРАММЫ:

OBCHIE SVEDENIYA

Tip kompa IBM PC/AT

Versiya MSDOS 5.0

data sozdaniya BIOSa-03/28/02

PAMYAT'

kollicestvo osnovnoi pamyati(Kb)-640

kollicestvo dopolnitel'noi pamyati(Kb)-34336

Pamyat' video stranichi(bait)-4096

DISKI

Diskovod A: na 1.44 Mb, dlya disket diametrom 3.5

Diskovod B:Diskovoda net ili ego tip neizvesten

Kolichestvo zhestkih magnitnih diskov-0

VIDEO

Adapter VGA-chvetnoi analogovii displai

DOPOLNITEL'NIE SVEDENIYA

est' matematicheskii soprochessor

igrovoi adapter otsytstvyet

posledovatel'nii printer ne ystanovlen

kolichestvo poslrdovatel'nih portov-4

kolichestvo paralel'nih portov-3

Изучение методов трансляции выражений в польскую инверсную запись (ПОЛИЗ).

Постановка задачи

Разработать программу для трансляции выражений в ПОЛИЗ логического выражения в языке Pascal.

Таблица приоритетов.

Метод построения ПОЛИЗА основан на использовании стека с приоритетами, позволяющего изменить порядок следования знаков операций в выражении так, что получается ПОЛИЗ. При этом каждому ограничителю, входящему в выражение, присваивается приоритет. Для знаков операции приоритеты возрастают в порядке, обратном старшинству операций. Скобки имеют низший приоритет.

В логических выражениях языка Pascal приоритеты у операций следующие:

1. not

2. *, /, and

3. +, -, or, xor

4. =, <>, <, >,<=, >=

Для программы приоритеты у знаков будут следующие:

0. (

1. )

2. =, <>, <, >, <=, >=

3. +, -, or, xor

4. *, /, and

5. not

Описание входных и выходных данных

Входными данными для программы является строка, содержащая логическое выражение (оно должно быть верным, т.к. проверка на ошибки не производится). Во входной строке все операнды могут представлять большими буквами латинского алфавита и цифрами (длина каждого операнда один символ), а операции кодируются следующим образом:

Операция

Код

+

+

-

-

*

*

/

/

=

=

<>

 

!

<

 

<

 

>

 

>

 

<=

l

>=

g

not

n

and

a

or

o

xor

x

Выходными данными является строка, содержащая ПОЛИЗ. Кодирование в ней такой же, как и во входной строке.

Также в программе применяется внутреннее кодирование символов для удобства построения ПОЛИЗА. Кодирование следующее: если символ операнд, то он не кодируется (остаётся таким же), если символ знак операции, то первый бит его кода принимает значение ‘1’, следующие три бита содержат приоритет, а последние четыре номер в массиве знаков операции. (const char ChInSt[]={'(', ')', 'n', '*', '/', 'a', '+', '-', 'o', 'x', '=', '!', '<', '>', 'g', 'l', '#'};)

Для работы используется стек с элементами типа char.

Описание алгоритма

Арифметическое или логическое выражение рассматривается как входная строка символов. Входная строка рассматривается слева направо. Операнды переписываются в выходную строку, а знаки операций помещаются вначале в стек операций.

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

Особенности имеет лишь обработка скобок. Открывающаяся круглая скобка, имеющая "особый" приоритет нуль, просто записывается в вершину стека и не выталкивает ни одного знака. В то же время ее не может вытолкнуть ни один знак, кроме закрывающей скобки.

Закрывающая скобка имеет приоритет 1, не превосходящий приоритет любой операции. Поэтому появление закрывающей скобки вызывает выталкивание всех знаков до ближайшей открывающей скобки включительно. В стек закрывающая скобка не записывается. Открывающая и закрывающая скобки как бы взаимно уничтожаются и в выходную строку не переносятся.

После просмотра всех символов входной cтроки происходит выталкивание всех оставшихся в стеке символов и дописывание их к выходной строке.

Тестовые примеры

1. Входная строка – “A+B”

Result:

AB+

2. Входная строка – “A+B!3”

Result:

AB+3!

3. Входная строка – “A+B=3*ZaC!2”

Result:

AB+3Z*Ca=2!

4. Входная строка – “A*(B+C)<7”

Result:

ABC+*7<

5. Входная строка – “A*(B-C/(L-9))gM”

Result:

ABCL9-/-*Mg

Текст программы

stack.h

template <class T> class Stack;

template <class T>

class Node

{

friend class Stack<T>;

private:

T *node;

Node<T> *p;

public:

Node (const T &t);

~Node();

};

template <class T>

class Stack

{

private:

Node<T> *lp;

public:

Stack();

~Stack();

void Push(T);

bool Pop(T *);

};

stack.cpp

//---------------------------------------------------------------------------

#include "stack.h"

#include <stddef.h>

//---------------------------------------------------------------------------

template <class T>

Node<T>::Node (const T &t): node(new T(t)), p(NULL){}

//---------------------------------------------------------------------------

template <class T>

Node<T>::~Node()

{

if (p)

delete p;

delete node;

}

//---------------------------------------------------------------------------

template <class T>

Stack<T>::Stack(): lp(NULL){}

//---------------------------------------------------------------------------

template <class T>

Stack<T>::~Stack()

{

if (lp)

delete lp;

}

//---------------------------------------------------------------------------

template <class T>

void Stack<T>::Push(T n)

{

Node<T> *new_node=new Node<T>(n);

new_node->p=lp;

lp=new_node;

}

//---------------------------------------------------------------------------

template <class T>

bool Stack<T>::Pop(T *n)

{

if (lp)

{

*n=*(lp->node);

Node<T> *del_node=lp;

lp=lp->p;

del_node->p=NULL;

delete del_node;

}

else return 0;

return 1;

}

//---------------------------------------------------------------------------

lab5.cpp

//---------------------------------------------------------------------------

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused

//---------------------------------------------------------------------------

#include <iostream.h>

#include <conio.h>

#include "stack.cpp"

#include <string.h>

//---------------------------------------------------------------------------

const char ChInSt[]={'(', ')', 'n', '*', '/', 'a', '+', '-', 'o', 'x', '=', '!', '<', '>', 'g', 'l', '#'};

char *POLIZ(char *);

char *Code(char *);

char *Decode(char *);

//---------------------------------------------------------------------------

void main()

{

clrscr();

char st[200], *resP, *res;

cout<<"Input string"<<endl;

cin>>st;

res=Code(st);

resP=POLIZ(res);

delete res;

res=Decode(resP);

cout<<"Result:"<<endl<<res<<endl;

getch();

delete res, resP;

}

//---------------------------------------------------------------------------

char *POLIZ(char *st)

{

Stack<char> s;

char n;

int prior, j=0;

char *res=new char[strlen(st)];

for (unsigned int i=0; i<strlen(st); i++)

{

if (!(st[i]&0x80))

{

res[j++]=st[i];

continue;

}

if (st[i]&0x0F)

{

prior=st[i]&0x70;

while (s.Pop(&n))

if ((n&0x70)>=prior)

res[j++]=n;

else

{

if (prior!=0x10)

s.Push(n);

break;

}

}

if (prior!=0x10)

s.Push(st[i]);

}

while (s.Pop(&n))

res[j++]=n;

res[j]=0;

return res;

}

//---------------------------------------------------------------------------

char *Code(char *st)

{

char *res=new char[strlen(st)+1];

strnset(res, 0, strlen(st)+1);

int j;

for (unsigned int i=0; i<strlen(st); i++)

{

for (j=0; j<17; j++)

if (st[i]==ChInSt[j])

break;

switch (j)

{

case 0: res[i]=0x80; break;

case 1: res[i]=j+0x90; break;

case 2: res[i]=j+0xD0; break;

case 3: case 4: case 5: res[i]=j+0xC0; break;

case 6: case 7: case 8: case 9: res[i]=j+0xB0; break;

case 10: case 11: case 12: case 13: case 14: case 15: res[i]=j+0xA0; break;

case 17: res[i]=st[i];

}

}

return res;

}

//---------------------------------------------------------------------------

char *Decode(char *st)

{

char *res=new char[strlen(st)+1];

for (unsigned int i=0; i<strlen(st); i++)

{

if (st[i]&0x80)

res[i]=ChInSt[st[i]&0x0F];

else res[i]=st[i];

}

res[strlen(st)]=0;

return res;

}

//---------------------------------------------------------------------------

Изучение команд языка Ассемблер, предназначенных для обработки строк символов.

 

Постановка задачи

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

    ПП

Данные

КС

КК

ПП - преамбула (4 байта с кодом 55Н);

Данные - поле данных (16 байт);

КС - контрольная сумма (2 байта);

КК - конец кадра (1 байт с кодом 1FН).

Под формированием понимается заполнение поля данных кадра и формирование контрольной суммы. Данные для передачи хранятся в области памяти с именем SDATA и представляют собой последовательность 16 символов из набора от A до Z и от 0 до 9. При формировании кадра данные необходимо зашифровать согласно таблице кодировки.

Контрольная сумма формируется как арифметическая сумма всех байт поля данных.

В лабораторной работе использовать команды работы со строками:

LODS,STOS и др.

Таблицы кодировки:

A

Q

K

3

U

R

3

M

B

L

L

D

V

9

4

V

C

O

M

X

W

B

5

N

D

T

N

7

X

H

6

E

E

W

O

4

Y

5

7

Y

F

G

P

U

9

0

8

J

G

Z

Q

P

Z

8

 

 

H

C

R

6

0

I

 

 

I

1

S

Z

1

F

 

 

J

A

T

S

2

K

 

 

Описание алгоритма

  1. В строку-результат записывается преамбула.
  2. Далее в цикле, который повторяется 16 раз, выполняются следующие действия:
    1. загрузка очередного символа из строки с данными;
    2. поиск соответствующего символа в первой строке таблицы кодировки;
    3. вычисление адреса соответствующего закодированного символа (к адресу второй строки таблицы прибавляется значение регистра СХ) и сохранение его в регистре АL;
    4. запись этого символа в строку-результат.
  3. Установка значения регистра SI на адрес начала данных в выходной строке.
  4. Подсчёт контрольной суммы (в цикле загружается каждый символ строки и складывается с значением в регистре ВХ в результате в ВХ будет храниться контрольная сумма).
  5. Запись контрольной суммы в выходную строку.
  6. Запись признака конца кадра в выходную строку.

Описание входных и выходных данных

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

Выходными данными является кадр. Для него резервируется место в 23 байта.

Текст программы

;------------------------------------------------------

LAB6 SEGMENT

ASSUME CS:LAB6,DS:LAB6,SS:LAB6

ORG 100H

BEGIN: JMP MAIN

;------------------------------------------------------

SDATA DB 'SDFSD12YGVF6RT92'

PP DB 4 DUP(55H)

KK DB 1FH

ABC DB 'ABCDEFGHIJKLMNOPQRSTUVWXY9Z012345678'

ABC_C DB 'QLOTWGZC1A3DX74UP6ZSR9BH508IFKMVNEYJ'

RES DB 23 DUP(?)

;------------------------------------------------------

MAIN: CLD

LEA SI,PP

LEA DI,RES

MOV CX,2

REP MOVSW

LEA SI,SDATA

MOV CX,16

CYCLE: LODSB

MOV DX,DI

LEA DI,ABC+35

MOV BX,CX

STD

MOV CX,36

REPNE SCASB

MOV BP,CX

ADD BP,OFFSET ABC_C

MOV AL,[BP]

MOV DI,DX

CLD

STOSB

MOV CX,BX

LOOP CYCLE

XOR BX,BX

XOR AX,AX

MOV CX,16

LEA SI,RES+4

CHECK: LODSB

ADD BX,AX

LOOP CHECK

MOV AX,BX

STOSW

MOV AL,KK

STOSB

INT 20H

LAB6 ENDS

END BEGIN

;------------------------------------------------------

Результаты тестирования

В результате работы программы вы из строки 'SDFSD12YGVF6RT92' должны получить следующее

55Н 55Н 55Н 55Н

‘ZTGZTFK5Z9GE6S0K’

8CH 04H (1164)

1FH

В результате работы получено:

clip_image002

Результата находится по адресам [0160]-[0177]

Вывод

В результате работы мною были изучены команд языка Ассемблер, предназначенных для обработки строк символов.