Определения, описанные в этом документе, объявлены в файле 'sys_h.asm', который в свою очередь линкует файл 'sysdefs.asm'. Данный документ подразумевает использование асм-компилятора sjasmplus из репозитория NedoOS. sjasmplus поставляется в виде исполнияемого файла sjasmplus.exe для OS Windows. А также в виде исходного кода для самостоятельной сбоки под вами используюмую OS. ************************* Используемые выражения ************************* байт - минимальня единица хранения данных в ОЗУ ZX-Spectrum, равная 8 битам. 0x - приставка к константе, обозначающая число представленном в шестнадцатиричной систаме измерения. хост(host) - точка подключения errno - номер ошибки big-endian - представление числа в ОЗУ. Сначала старший байт, затем младший. К примеру 16 битное число 0x1234 располагается в памяти как DEFB 0x12,0x34 little-endian - представление числа в ОЗУ. Это представление использует процессор z80. Сначала младший байт, затем старший. В этом документе, по умолчанию, все числа little-endian. К примеру 16 битное число 0x1234 располагается в памяти как DEFB 0x34,0x12 SOCKET - дескриптор сокета. Знаковое 8-битное число. sockaddr_in - структура, размером 15 байт, со следующими полями: sin_family - семейство адресов, беззнаковое 8-битное число. в текущей реализации допускается только значение 2 (AF_INET). sin_port - номер порта, 16-битное беззнаковое big-endian число. sin_addr - IP-адрес. Массив из четырёх 8-битных беззнаковых чисел. к примеру IP-адрес 1.2.3.4 располагается в памяти как defb 1,2,3,4 sin_zero - зарезервировано. массив из 8 байт. ************************* Возможные номера ошибок (errno)************************* SHUT_RDWR EQU 2 ERR_EAGAIN EQU 35 ;/* Try again */ ERR_EWOULDBLOCK EQU ERR_EAGAIN ;/* Operation would block */ ERR_INTR EQU 4 ERR_NFILE EQU 23 ERR_ALREADY EQU 37 ERR_NOTSOCK EQU 38 ERR_EMSGSIZE EQU 40 ;/* Message too long */ ERR_PROTOTYPE EQU 41 ERR_AFNOSUPPORT EQU 47 ERR_HOSTUNREACH EQU 65 ERR_ECONNABORTED EQU 53 /* Software caused connection abort */ ERR_CONNRESET EQU 54 ERR_NOTCONN EQU 57 ************************* Протоколы соединений ************************* SOCK_STREAM EQU 0x01 ;tcp/ip SOCK_ICMP EQU 0x02 ;icmp SOCK_DGRAM EQU 0x03 ;udp/ip AF_INET EQU 2 *********************************************************** *********************** Определения *********************** *********************************************************** При вызове функций ядра считается, что возможна порча всех регистров(за исключением SP). Все вызовы не блокирующие(за исключением OS_NETCONNECT), т.е. не ожидадают отправку\прием данных, либо подключения. При необходимости использования блокирующих функций - реализовывать самостоятельно внутри процесса. *********************** OS_NETSOCKET ********************** Создаёт сокет. Макрос вызова функции ядра. Все аргументы в регистрах: D - семейство адресов, беззнаковое 8-битное число, допускается только значение 2 (AF_INET). E - протокол соединения(0x01 tcp/ip, 0x02 icmp, 0x03 udp/ip) Возвращаемые значения в регистрах: L - SOCKET при положительном значении, при отрицательном значении - функция завершилась с ошибкой. А - errno при ошибке. Возможные ошибки: ERR_AFNOSUPPORT - семейство адресов не поддерживается ERR_NFILE - нет свободных сокетов ERR_PROTOTYPE - протокол не поддерживается Пример создания TCP/IP сокета: LD D,AF_INET;2 LD E,SOCK_STREAM OS_NETSOCKET BIT 7,L JP NZ,ERR_EXIT ;обработка ошибки LD A,L LD (SOC),A ;сохраняем дескриптор сокета. Примечания: При закрытии процесса, закрываются все сокеты созданные этим процессом. Сокеты защищены от использования другим процессом. Номер исходящего порта присваивается автоматически из диапазона 49152...65535 *********************** OS_NETSHUTDOWN ********************** Закрытие сокета. Макрос вызова функции ядра. Все аргументы в регистрах: A - SOCKET E - Варианты закрытия, 0 - закрыть немедленно, 1 - закрыть только если буфер отправки пуст. Возвращаемые значения в регистрах: L - При отрицательном значении - функция завершилась с ошибкой. А - errno при ошибке. Пример закрытия сокета с ожиданием опустошения буфера отправки: close_wait: LD A,(SOC) LD E,1 OS_NETSHUTDOWN BIT 7,L RET Z ;сокет закрылся CP ERR_EAGAIN JP NZ,ERR_EXIT ;обработка ошибки не связанной с ожиданием отправки. OS_YIELD ;не обязательно. Если время не критично, ;то отдадим квант времени системе. JR close_wait ;ожидаем отправки данных Возможные ошибки: ERR_NOTSOCK - не действительный дескриптор сокета ERR_EAGAIN - буфер отправки не пуст Примечание: Керналь закрывает сокеты процесса при закрытии процесса. Но, ввиду ограниченного количества сокетов, рекомендуется закрывать сокет как только он становится не нужен. *********************** OS_NETCONNECT ********************** Подключить TCP/IP сокет к хосту. Макрос вызова функции ядра. Все аргументы в регистрах: A - SOCKET DE - указатель на структуру sockaddr_in содержащую IP адрес и порт хоста. Возвращаемые значения в регистрах: L - При отрицательном значении - функция завершилась с ошибкой. А - errno при ошибке. Возможные ошибки: ERR_NOTSOCK - не действительный дескриптор сокета ERR_ALREADY - сокет уже подключен ERR_HOSTUNREACH - хост не доступн, либо отверг подключение. Пример подключения к хосту с IP адресом 1.2.3.4 на порт 80: LD A,(SOC) LD DE,destination_host OS_NETCONNECT BIT 7,L JP NZ,ERR_EXIT ;обработка ошибки ... ;подключились destination_host DEFB AF_INET DEFB 0,80 ;порт назначения DEFB 1,2,3,4 ;IP адрес назначения DEFB 0,0,0,0,0,0,0,0 ;резерв Примечание: Данная функция применима только к TCP/IP сокетам. *********************** OS_BIND ********************** Присвоение сокету конкретного номера исходящего порта. Макрос вызова функции ядра. Все аргументы в регистрах: A - SOCKET DE - указатель на структуру sockaddr_in содержащую номер исходящего порта. (остальные поля структуры не используются, но обязаны присутствовать) Возвращаемые значения в регистрах: L - При отрицательном значении - функция завершилась с ошибкой. А - errno при ошибке. Возможные ошибки: ERR_NOTSOCK - не действительный дескриптор сокета Пример присвоения сокету исходяего порта 433: LD A,(SOC) LD DE,source_host OS_BIND BIT 7,L JP NZ,ERR_EXIT ;обработка ошибки ... ;удачно, продолжаем работу source_host DEFB AF_INET DEFB high(433),low(433) ;исходящий порт DEFB 0,0,0,0 ;исходящий IP адрес (не используется в текущей реализации) DEFB 0,0,0,0,0,0,0,0 ;резерв Примечание: В режиме TCP/IP функция вызывается(если нужна) до вызовов OS_NETCONNECT или OS_LISTEN. *********************** OS_LISTEN ********************** Включить режим прослушивания исходящего порта(режим сервера) TCP/IP сокета. Макрос вызова функции ядра. Все аргументы в регистрах: A - SOCKET Возвращаемые значения в регистрах: L - При отрицательном значении - функция завершилась с ошибкой. А - errno при ошибке. Возможные ошибки: ERR_NOTSOCK - не действительный дескриптор сокета ERR_ALREADY - сокет уже подключен Пример включения режима прослушивания: LD A,(SOC) OS_LISTEN BIT 7,L JP NZ,ERR_EXIT ;обработка ошибки ... ;удачно, продолжаем работу Примечание: Данная функция применима только к TCP/IP сокетам. Как правило функция вызывается(если нужна) после вызова OS_BIND. *********************** OS_ACCEPT ********************** Принять входящее TCP/IP подключение. Макрос вызова функции ядра. Все аргументы в регистрах: A - SOCKET Возвращаемые значения в регистрах: L - SOCKET при положительном значении, при отрицательном значении - функция завершилась с ошибкой. А - errno при ошибке. Возможные ошибки: ERR_NOTSOCK - не действительный дескриптор сокета ERR_ECONNABORTED - общая ошибка сокета ERR_EAGAIN - входящих подключений пока нет Пример принятия соединения с ожиданием подключения: WAIT_CLIENTS LD A,(SOC) OS_ACCEPT BIT 7,L JR Z,ESTABLISHED CP ERR_EAGAIN JP NZ,ERR_EXIT ;обработка ошибки OS_YIELD ;не обязательно. Если время реагирования на подключение не критично, ;то отдадим квант времени системе. JR WAIT_CLIENTS ;никто не подключился, ждём ESTABLISHED LD A,L ;удачно LD (SOC_CLIENT),A ;сохраняем дескриптор сокета. ... ;продолжаем работу Примечания: Данная функция применима только к TCP/IP сокетам. Функция вызывается после вызова OS_LISTEN. Возвращает новый дескриптор сокета с принятым соединением. Сокет прослушки продолжает слушать. Если дальнейшая прослушка не требуется, то рекомендуется сразу закрывать слушающий сокет. При недостатке сокетов, возвращается дескриптор подключенного сокета прослушки, в этом случае нет дальнейшего прослушивания. Т.е. при закрытии слушающего сокета, необходимо проверить(путем сравнения дескрипторов) не является ли он сокетом с принятым соединением. *********************** OS_WIZNETREAD ********************** Прочитать входящие данные. Макрос вызова функции ядра. При протоколе TCP/IP все аргументы в регистрах: A - SOCKET DE - указатель на буфер для принятия данных HL - размер буфера(в байтах) При протоколе отличном от TCP/IP все аргументы в регистрах: A - SOCKET DE - указатель на структуру sockaddr_in, в неё помещается(ядром) IP-адрес и порт хоста отправившего данные. IX - указатель на буфер для принятия данных HL - размер буфера(в байтах) Возвращаемые значения в регистрах: HL - при отрицательном значении функция завершилась с ошибкой, про значении больше нуля возвращается действительный размер(в байтах) принятых данных, нулевого значения вызов не возвращает. А - errno при ошибке. Возможные ошибки: ERR_NOTSOCK - не действительный дескриптор сокета ERR_EAGAIN - входящих данных пока нет ERR_NOTCONN - сокет с неустановленным\пропавшем соединением(при протоколе TCP/IP) Пример принятия данных по протоколу TCP/IP с ожиданием данных: WAIT_DATA LD A,(SOC) LD DE,BUF LD HL,BUF_SIZE OS_WIZNETREAD BIT 7,H JR Z,RECEIVED ;ошибок нет CP ERR_EAGAIN JP NZ,ERR_EXIT ;обработка ошибки OS_YIELD ;не обязательно. Если время реагирования на пришедшие данные не критично, ;то отдадим квант времени системе. JR WAIT_DATA ;данных нет, ждём RECEIVED LD (DATA_SIZE),HL ;удачно. если требуется, то сохраняем количество принятых данных. ... ;продолжаем работу BUF DEFS 1000 BUF_SIZE EQU $-BUF Примечания: При протоколе отличном от TCP/IP, необходимо единовременно прочитать весь пакет, иначе недовычитанные данные пакета игнорируются. *********************** OS_WIZNETWRITE ********************** Отправить пакет данных. Макрос вызова функции ядра. При протоколе TCP/IP все аргументы в регистрах: A - SOCKET DE - указатель на буфер с данными HL - размер данных(в байтах), в текущей реализации максимум 8192 байта При протоколе отличном от TCP/IP все аргументы в регистрах: A - SOCKET DE - указатель на структуру sockaddr_in, в неё необходимо поместить IP-адрес и порт хоста получателя IX - указатель на буфер с данными HL - размер данных(в байтах), в текущей реализации максимум 8192 байта Возвращаемые значения в регистрах: HL - при отрицательном значении функция завершилась с ошибкой, иначе возвращается действительный размер(в байтах) отправленных данных, А - errno при ошибке. Возможные ошибки: ERR_NOTSOCK - не действительный дескриптор сокета ERR_NOTCONN - сокет с неустановленным\пропавшем соединением(при протоколе TCP/IP) ERR_EMSGSIZE - в буфере отправки нет места, либо пакет слишком большой Пример отправки данных по протоколу TCP/IP с ожиданием данных: WAIT_SEND LD A,(SOC) LD DE,BUF LD HL,BUF_SIZE OS_WIZNETWRITE BIT 7,H JR Z,SEND_OK ;ошибок нет CP ERR_EMSGSIZE JP NZ,ERR_EXIT ;обработка ошибки OS_YIELD ;не обязательно. Если время не критично, ;то отдадим квант времени системе. JR WAIT_SEND ;буфер отправки переполнен, ждём освобождения SEND_OK LD (DATA_SIZE),HL ;удачно. если требуется, то сохраняем количество отправленных данных. ... ;продолжаем работу BUF DEFB "Hello World!" BUF_SIZE EQU $-BUF