/* * lseek — 32-битная позиция файла через ESTEX MOVE_FP ($15). * * ESTEX MOVE_FP: A=handle, B=whence (0=SET, 1=CUR, 2=END), * HL=offset high16, IX=offset low16 * возврат: HL:IX = новая абсолютная позиция, CF=err * * SDCC __sdcccall(1) на z80 для `long lseek(int fd, long offset, int whence)`: * - fd — HL (первый 16-битный аргумент в регистре) * - offset — на стеке двумя 16-битными словами (сначала low, потом high) * - whence — на стеке (выше offset) * - 32-битный возврат: DE = low16, HL = high16 * - стек чистит вызывающий (`pop af; pop af; pop af` после call) * * IX сохраняется (frame pointer вызывающего). */ #include long lseek(int fd, long offset, int whence) __naked { (void)fd; (void)offset; (void)whence; __asm push ix ; сохранить IX вызывающего ;; Раскладка после push: ;; SP+0..1 = сохранённый IX ;; SP+2..3 = адрес возврата ;; SP+4..5 = offset low16 ;; SP+6..7 = offset high16 ;; SP+8..9 = whence ld a, l ; A = младший байт fd (был в HL) ;; 5 последовательных байтов стека читаем через HL — дешевле, ;; чем IY-индексация: `ld r,(hl); inc hl` (2Б/13Т на байт) ;; против `ld r, n(iy)` (3Б/19Т) при последовательном чтении. ld hl, #4 add hl, sp ; HL указывает на offset_low ld e, (hl) inc hl ld d, (hl) ; DE = offset_low push de pop ix ; IX = offset_low inc hl ld e, (hl) inc hl ld d, (hl) ; DE = offset_high inc hl ld b, (hl) ; B = whence (младший байт) ex de, hl ; HL = offset_high (ESTEX ждёт его тут) ld c, #0x15 ; ESTEX MOVE_FP rst #0x10 jr c, _lseek_err ;; Вернулось HL:IX = новая позиция. Приводим к long-возврату ;; SDCC (DE:HL). push ix pop de ; DE = low16 (был IX) ;; HL уже содержит high16 pop ix ; восстановить IX вызывающего ret _lseek_err: call __errno_set ld hl, #0xFFFF ld de, #0xFFFF ; long -1 pop ix ret __endasm; }