x86 레지스터 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

"""x86 레지스터 검증 (MASM이 없어 파이썬 흉내로 확인).

문서: 04.x86 레지스터
주장:
  1. EAX(32비트)의 아래 16비트가 AX, AX의 위 8비트가 AH, 아래 8비트가 AL이다.
     AL에 써도 나머지 24비트는 그대로이고, AX에 써도 위 16비트는 그대로다. 8비트 전수 검사.
  2. 예: EAX = 12345678h → AX = 5678h, AH = 56h, AL = 78h.
     AL ← FFh → EAX = 123456FFh. AH ← 00h → 123400FFh. AX ← ABCDh → 1234ABCDh.
  3. 8비트 이름이 있는 것은 EAX·EBX·ECX·EDX 넷뿐, ESI·EDI·EBP·ESP는 16비트 이름만 있다.
  4. 문서 예제의 디버거 출력 EFL = 00000206h 를 비트로 풀면 CF = 0, ZF = 0, SF = 0, OF = 0 이고
     짝수 플래그(PF)와 인터럽트 허용(IF) 비트가 1이다. 표시된 CF/SF/ZF/OF 값과 맞는다.
  5. 짝수 플래그: 결과 아래 8비트에서 1의 개수가 짝수면 1. 00h → 1, 0Bh → 0.
"""


class Reg32:
    def __init__(self, v=0):
        self.e = v & 0xFFFFFFFF

    @property
    def x(self):                 # 16비트 이름 (AX)
        return self.e & 0xFFFF

    @x.setter
    def x(self, v):
        self.e = (self.e & 0xFFFF0000) | (v & 0xFFFF)

    @property
    def h(self):                 # 위 8비트 (AH)
        return (self.e >> 8) & 0xFF

    @h.setter
    def h(self, v):
        self.e = (self.e & 0xFFFF00FF) | ((v & 0xFF) << 8)

    @property
    def l(self):                 # 아래 8비트 (AL)
        return self.e & 0xFF

    @l.setter
    def l(self, v):
        self.e = (self.e & 0xFFFFFF00) | (v & 0xFF)


FLAG_BIT = {"CF": 0, "PF": 2, "AF": 4, "ZF": 6, "SF": 7, "IF": 9, "DF": 10, "OF": 11}


def flags_of(efl):
    return {name: (efl >> bit) & 1 for name, bit in FLAG_BIT.items()}


def parity_flag(result):
    return 1 if bin(result & 0xFF).count("1") % 2 == 0 else 0


def main():
    a = Reg32(0x12345678)
    assert (a.x, a.h, a.l) == (0x5678, 0x56, 0x78)
    a.l = 0xFF
    assert a.e == 0x123456FF
    a.h = 0x00
    assert a.e == 0x123400FF
    a.x = 0xABCD
    assert a.e == 0x1234ABCD
    print("[OK] EAX = 12345678h → AX 5678h, AH 56h, AL 78h, 부분 쓰기 세 가지")

    for v in range(256):
        r = Reg32(0xDEADBEEF)
        r.l = v
        assert r.e >> 8 == 0xDEADBE and r.l == v
        r = Reg32(0xDEADBEEF)
        r.h = v
        assert r.e & 0xFFFF00FF == 0xDEAD00EF and r.h == v
        r = Reg32(0xDEADBEEF)
        r.x = v * 257
        assert r.e >> 16 == 0xDEAD and r.x == v * 257
        assert r.x == r.h * 256 + r.l
    print("[OK] 8비트 값 256개 전부: 한 조각에 써도 다른 조각은 그대로, AX = AH*256 + AL")

    table = {"EAX": ("AX", "AH", "AL"), "EBX": ("BX", "BH", "BL"),
             "ECX": ("CX", "CH", "CL"), "EDX": ("DX", "DH", "DL")}
    only16 = {"ESI": "SI", "EDI": "DI", "EBP": "BP", "ESP": "SP"}
    assert len(table) == 4 and len(only16) == 4
    assert len(table) + len(only16) == 8          # 범용 레지스터 여덟 개
    assert len(["CS", "SS", "DS", "ES", "FS", "GS"]) == 6
    print("[OK] 범용 8개(8비트 이름 있는 것 4개), 세그먼트 6개")

    f = flags_of(0x00000206)
    assert (f["CF"], f["SF"], f["ZF"], f["OF"]) == (0, 0, 0, 0)
    assert f["PF"] == 1 and f["IF"] == 1 and f["AF"] == 0
    assert 0x206 == (1 << 9) | (1 << 2) | (1 << 1)
    print("[OK] EFL = 206h: CF = SF = ZF = OF = 0, PF = 1, IF = 1")

    assert parity_flag(0x00030000) == 1 and parity_flag(0x0000000B) == 0
    assert parity_flag(0b10110010) == 1 and parity_flag(0b10110011) == 0
    print("[OK] 짝수 플래그: 00h → 1, 0Bh(1이 세 개) → 0")

    # 카드: EBX = 0000A1B2h 에서 BL ← 00h, BH ← FFh
    b = Reg32(0x0000A1B2)
    b.l = 0x00
    assert b.e == 0x0000A100
    b.h = 0xFF
    assert b.e == 0x0000FF00 and b.x == 0xFF00
    # 카드: ECX = FFFFFFFFh 에서 CX ← 0
    c = Reg32(0xFFFFFFFF)
    c.x = 0
    assert c.e == 0xFFFF0000
    print("[OK] 카드: EBX A1B2h → A100h → FF00h, ECX FFFFFFFFh → FFFF0000h")
    print("ALL CHECKS PASSED")


if __name__ == "__main__":
    main()