libc: квирки DSS — возврат WRITE и лимит манипуляторов; тесты fdmax/fbench
- ESTEX WRITE ($14) на успехе возвращает DE=0, а НЕ счётчик записанного (вопреки докам; solid-c в своём fflush тоже отключил сравнение по счётчику) — write() теперь судит по CF/A: CF=0&A=0 → n, CF=0&A!=0 → ENOSPC/-1 - DSS выдаёт 8 манипуляторов (fd 2..9; fd 1 держит шелл под запущенный exe), а 9-й OPEN не возвращает 06h — ВЕШАЕТ систему; предохранитель _fd_guard: счётчик в open()/close(), отказ EMFILE без захода в DSS - tests/fdmax — эмпирика лимита (8 хендлов, затем EMFILE=6); tests/fbench — бенчмарк буферизации (floor 512-байтными read, оценка небуферизованного по 1-байтным, fgetc/fgets/fputc) - filetest расширен: raw-probe возврата write, сценарий r+ (чтение-запись-чтение с инвалидацией буфера), ungetc, fprintf Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* write — блочная запись в файловый хендл ESTEX.
|
||||
*
|
||||
* ESTEX WRITE ($14): A=handle, HL=буфер, DE=число байт
|
||||
* → CF=err с кодом в A.
|
||||
*
|
||||
* КВИРК (подтверждён в MAME, DSS 1.71.57, 2026-07-06): вопреки докам
|
||||
* («DE = реальное количество записанных байт») на успехе DE = 0.
|
||||
* Достоверный признак полной записи — A = 0 при CF = 0 (как у READ,
|
||||
* где A=0 «всё», A=FFh «меньше»); solid-c в своём fflush так же
|
||||
* закомментировал сравнение по DE и проверяет A. Поэтому:
|
||||
* CF=1 → errno из A, возврат -1;
|
||||
* CF=0, A=0 → всё записано, возврат n (запрошенного);
|
||||
* CF=0, A!=0 → частичная запись (диск полон), реальный счётчик
|
||||
* неизвестен → errno=ENOSPC, возврат -1.
|
||||
*
|
||||
* ABI-паттерн идентичен read() — см. read.c.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int write(int fd, const void *buf, size_t n) __naked
|
||||
{
|
||||
(void)fd; (void)buf; (void)n;
|
||||
__asm
|
||||
pop iy ; IY = адрес возврата
|
||||
pop bc ; BC = n (стековый аргумент)
|
||||
ld a, l ; A = handle
|
||||
ex de, hl ; HL = buf
|
||||
ld d, b
|
||||
ld e, c ; DE = n
|
||||
push bc ; n нужен после RST (всё клобберится)
|
||||
push ix
|
||||
push iy ; сохранить адрес возврата через RST
|
||||
ld c, #0x14 ; ESTEX WRITE
|
||||
rst #0x10
|
||||
pop iy
|
||||
pop ix
|
||||
pop bc ; BC = n
|
||||
jr c, _write_err
|
||||
or a, a ; A=0 — всё записано (DE недостоверен)
|
||||
jr nz, _write_short
|
||||
ld d, b
|
||||
ld e, c ; вернуть запрошенное n
|
||||
jp (iy)
|
||||
_write_short:
|
||||
ld a, #10 ; ENOSPC (DSS 0Ah No free space)
|
||||
_write_err:
|
||||
call __errno_set
|
||||
ld de, #-1
|
||||
jp (iy)
|
||||
__endasm;
|
||||
}
|
||||
Reference in New Issue
Block a user