SUPPLIED ENSEMBLE1.2 KERNEL: TIMER AND EXCEPTION ABI AUDIT

Input: work/runtime/GWSVGA/KERNEL.EXE,72736bytes.
Addresses below are FILE byte offsets, not relocated runtimeCS:IP.
DOS executable image starts at file0x600.

TimerSleep is identified by its exact instruction sequence matching the retained
kernel source and the native Bounce sleep call(kernel ordinal0xb8, AX=ticks).

FILE0xa690:
  push ax
  push cx
  push dx
  push bx
  push ds
  mov cx,ax
  xor dx,dx
  mov al,8             ; TIMER_SLEEP in this kernel
  push cs
  call0xa637           ; TimerStart
  push bx
  mov ax,0xe34
  mov ds,ax
  add bx,0xe
  call0xa275           ; BlockOnLongQueue
  pop bx
  call0x7425           ; FreeHandle
  pop ds
  pop bx
  pop dx
  pop cx
  pop ax
  retf                 ; FILE0xa6b4

TimerStart FILE0xa637 saves/restores DI and DS. Its list insertion helper at
FILE0xa70a saves/restores SI and DI. FreeHandle0x7425 uses AX under a savedAX,
and does not modify SI/DI/BP/ES.

BlockOnLongQueue FILE0xa275:
  push ds
  push si
  push di
  push cx
  pushf
  push dx
  push es
  push bp
  ... queues/switches/waits ...
  The common restore tail FILE0xa104:
  pop bp
  pop es
  pop dx
  push cs
  call0x2ff3           ; restore saved FLAGS using kernel helper
  pop cx
  pop di
  pop si
  pop ds
  ret

Therefore low16 SI/DI/BP/ES are preserved by the actual old TimerSleep path,
including a context switch. There is no binary evidence for the hypothesis
that this call itself violates the normal Watcom callee-save ABI.

The old context switch saves only16bit register values. It does not preserve
the upper halves of EAX/EBX/ECX/EDX/ESI/EDI/EBP. Code that keeps meaningful
upper-register values across a thread switch is incompatible with this kernel.
This is a compatibility boundary, not proof of a particular crash's cause.
The port's8086 engine and runtime avoid that dependency.

Exception attribution:
FILE0xa401(default CPU exception):
  mov bp,sp
  mov bp,[bp+4]        ; interruptedCS from IRET frame
  pop si               ; pointer to inline exception number
  xor ax,ax
  mov al,[cs:si]
  call AddErrorInfo

AddErrorInfo FILE0x8e3:
  ... append 'Fatal error in '...
  mov cx,bp
  call SegmentToHandle ; FILE0x7849
  jnc useKernel
  mov bx,cx
  mov bx,[bx+8]        ; HM_owner
  mov ds,[bx]          ; owner coreblock segment
  mov si,0x14          ; GH_geodeName in runtime coreblock
  mov cx,8
  ...copy until space...
  ...append exception text...
useKernel:
  mov al,0xf           ; externalGEOS.STR string'kernel'
  call AddString

The message names the owner of the interruptedCS if its heap segment resolves.
The current thread owner is not used. If the interrupted segment cannot be
resolved, the formatter uses 'kernel' as a fallback. Consequently a message
naming kernel can describe a real kernel-address fault or an unresolved/stale
code segment; that label alone does not establish the underlying cause.
