• Please review our updated Terms and Rules here

Am I missing something ???

Ruud

Veteran Member
Joined
Nov 30, 2009
Messages
1,404
Location
Heerlen, NL
I'm disassembling the ROMs of the Commodore PC20-III and the PC-1. They are different but have common parts. But I found a piece of code that is driving me mad, more or less:
Code:
    ...
    and    ah,0C0h            ; filter parity and I/O check
    shl    ah,1            ; xx00 0000 -> x000 0000  (msb ... lsb)
    shl    ah,1            ; x000 0000 -> 0000 0000
; AH is always zero at this point or am I missing something?

    or    al,ah
    out    dx,al
The comment under the first three lines says it all.

Thank you for any input!
 
I think it's a programming error, the code makes sense if instead of SHL, an ROL is used. Then, the two high-order bits of AH are moved to the low-order positions and the OR with AL makes sense. It's also a bit faster than shifting AH right logically 6 bits.

Exactly what function does this code perform?
 
I simply don't know. Here is the full code of the routine:
Code:
;**  Checks if bit 6 and 7 have been set but
; in:    AH    ???
Chk8255C67:                ;                [FA39]
    push    dx

    mov    dx,PPI8255C
    in    al,dx
    xchg    ah,al            ; save read value and AL := AH
; This is why I think that AH is an input. Problem: it is not always set.

    call    ToggleParity        ;                [FA52]

    and    ah,0C0h            ; filter parity and I/O check
    shl    ah,1            ; xx00 0000 -> x000 0000  (msb ... lsb)
    shl    ah,1            ; x000 0000 -> 0000 0000
; And what do I miss ???

    or    al,ah
    out    dx,al

    test    ah, 30h
    pop    dx
    ret
Forget about the header, I made it up some years ago, but now, after having a good look, I'll scrap it.

What I see:
- read PPI8255C into AL
- swap it with AH. This made me decide that AH must be an input. Weird detail: in some cases AH is not provided when this routine is called.
- toggle the parity bits twice
- do the weird trick
- or AL, the original AH, with zero
- write it to PPI8255C
And that's it. In some cases anything can be written to PPI8255C but the PC doesn't crash. If the whole is a bug, the programmer of this made a lucky escape.
 
Are you sure you disassembled the shl ah, 1 correctly? Given the test ah, 30h near the end of the function, it would make sense that it was really shr ah, 1.
 
Can confirm:

Code:
seg000:FA3A sub_FA3A        proc near               ; CODE XREF: sub_C421+1E55p
seg000:FA3A                                         ; sub_C421+1F7Dp ...
seg000:FA3A                 push    dx
seg000:FA3B                 mov     dx, 62h ; 'b'
seg000:FA3E                 in      al, dx          ; PC/XT PPI port C. Bits:
seg000:FA3E                                         ; 0-3: values of DIP switches
seg000:FA3E                                         ; 5: 1=Timer 2 channel out
seg000:FA3E                                         ; 6: 1=I/O channel check
seg000:FA3E                                         ; 7: 1=RAM parity check error occurred.
seg000:FA3F                 xchg    ah, al
seg000:FA41                 call    sub_FA53
seg000:FA44                 and     ah, 11000000b
seg000:FA47                 shl     ah, 1
seg000:FA49                 shl     ah, 1
seg000:FA4B                 or      al, ah
seg000:FA4D                 out     dx, al
seg000:FA4E                 test    ah, 110000b
seg000:FA51                 pop     dx
seg000:FA52                 retn
seg000:FA52 sub_FA3A        endp

This is the PC-I BIOS. Definitely seems like a mistake.
 
That could be cycle / byte eaters. The original PC BIOS isn't the greatest x86 assembly ever written. Sometimes "bum code" to eat up a specific amount of cycles and bytes without using NOP was tossed into clone BIOS to make the code the same size or take the same amount of delay to execute, without using the exact same code as the original. That way programs that bypass the software interrupt system and call said routines directly remain fully compatible.

Could be as simple as a specific cycle count delay is needed between the call and the out.

Which can drive you nuts when looking at such "compatible but not written the same" code.
 
Back
Top