by shigemk2

当面は技術的なことしか書かない

レジスタの規則 #ikebin

7shi / ikebin / wiki / 8086 / regs — Bitbucket

アセンブリ

mov ax, #0
mov bx, #0
mov cx, #0
mov dx, #0
mov sp, #0
mov bp, #0
mov si, #0
mov di, #0

逆アセンブラ

let aout = System.IO.File.ReadAllBytes "regs.out"
let read16 (a:byte[]) b =
    (int a.[b]) ||| ((int a.[b + 1]) <<< 8)
let tsize = read16 aout 2
let dsize = read16 aout 4
let mem = Array.zeroCreate<byte> 0x10000
mem.[0 .. tsize + dsize - 1] <- aout.[16 .. 16 + tsize + dsize - 1]
let mutable ip = 0
let show len dis =
    let bin = [ for b in mem.[ip .. ip + len - 1] -> sprintf "%02x" b ]
    printfn "%04x: %-12s  %s" ip (String.concat "" bin) dis
    ip <- ip + len
while ip < tsize do
    match int mem.[ip], int mem.[ip + 1] with
    | 0xb8, _ ->
        show 3 (sprintf "mov ax, %04x" (read16 mem (ip + 1)))
    | 0xbb, _ ->
        show 3 (sprintf "mov bx, %04x" (read16 mem (ip + 1)))
    | 0xc7, 0x07 ->
        show 4 (sprintf "mov [bx], %04x" (read16 mem (ip + 2)))
    | 0xc7, 0x47 ->
        show 5 (sprintf "mov [bx+%x], %04x" mem.[ip + 2] (read16 mem (ip + 3)))
    | 0xc6, 0x07 ->
        show 3 (sprintf "mov byte [bx], %02x" mem.[ip + 2])
    | 0xc6, 0x47 ->
        show 4 (sprintf "mov byte [bx+%x], %02x" mem.[ip + 2] mem.[ip + 3])
    | 0x89, 0x07 ->
        show 2 (sprintf "mov [bx], ax")
    | 0x89, 0x4f ->
        show 3 (sprintf "mov [bx+%x], cx" mem.[ip + 2])
    | 0xb9, _ ->
        show 3 (sprintf "mov cx, %04x" (read16 mem (ip + 1)))
    | 0x88, 0x07 ->
        show 2 (sprintf "mov [bx], al")
    | 0x88, 0x67 ->
        show 3 (sprintf "mov [bx+%x], ah" mem.[ip + 2])
    | 0xb5, _ ->
        show 2 (sprintf "mov ch, %02x" mem.[ip + 1])
    | 0xb1, _ ->
        show 2 (sprintf "mov cl, %02x" mem.[ip + 1])
    | 0x89, 0x0f ->
        show 2 (sprintf "mov [bx], cx")
    | 0xc7, 0x06 ->
        show 6 (sprintf "mov [%04x], %04x" (read16 mem (ip + 2)) (read16 mem (ip + 4)))
    | 0xc6, 0x06 ->
        show 5 (sprintf "mov byte [%04x], %02x" (read16 mem (ip + 2)) mem.[ip + 4])
    | 0x81, 0x2e ->
        show 6 (sprintf "sub [%04x], %04x" (read16 mem (ip + 2)) (read16 mem (ip + 4)))
    | 0x80, 0x2e ->
        show 5 (sprintf "sub byte[%04x], %02x" (read16 mem (ip + 2)) mem.[ip + 4])
    | 0xba, _ ->
        show 3 (sprintf "mov dx, %04x" (read16 mem (ip + 1)))
    | 0xbc, _ ->
        show 3 (sprintf "mov sp, %04x" (read16 mem (ip + 1)))
    | 0xbd, _ ->
        show 3 (sprintf "mov bp, %04x" (read16 mem (ip + 1)))
    | 0xbe, _ ->
        show 3 (sprintf "mov si, %04x" (read16 mem (ip + 1)))
    | 0xbf, _ ->
        show 3 (sprintf "mov di, %04x" (read16 mem (ip + 1)))
    | 0xcd, 0x07 ->
        show 2 "int 7"
        match int mem.[ip] with
        | 1 ->
            show 1 "; exit"
        | 4 ->
            show 1 "; write"
            show 2 "; arg"
            show 2 "; arg"
        | _ ->
            show 1 "; ???"
    | 0xcd, n ->
        show 2 (sprintf "int %x" n)
    | _ ->
        show 1 "???"

インタプリタ

let aout = System.IO.File.ReadAllBytes "regs.out"
let read16 (a:byte[]) b =
    (int a.[b]) ||| ((int a.[b + 1]) <<< 8)
let write16 (a:byte[]) b c =
    a.[b] <- byte c
    a.[b + 1] <- byte (c >>> 8)

let tsize = read16 aout 2
let dsize = read16 aout 4
let mem = Array.zeroCreate<byte> 0x10000
mem.[0 .. tsize + dsize - 1] <- aout.[16 .. 16 + tsize + dsize - 1]
let mutable ax, bx, cx, dx, sp, bp, si, di, ip = 0, 0, 0, 0, 0, 0, 0, 0, 0
while ip < tsize do
    match int mem.[ip], int mem.[ip + 1] with
    | 0xb8, _ ->
        ax <- read16 mem (ip + 1)
        ip <- ip + 3
    | 0xbb, _ ->
        bx <- read16 mem (ip + 1)
        ip <- ip + 3
    | 0xc7, 0x07 ->
        write16 mem bx (read16 mem (ip + 2))
        ip <- ip + 4
    | 0xc7, 0x47 ->
        write16 mem (bx + (int mem.[ip + 2])) (read16 mem (ip + 3))
        ip <- ip + 5
    | 0xc6, 0x07 ->
        mem.[bx] <- mem.[ip + 2]
        ip <- ip + 3
    | 0xc6, 0x47 ->
        mem.[bx + (int mem.[ip + 2])] <- mem.[ip + 3]
        ip <- ip + 4
    | 0x89, 0x07 ->
        write16 mem bx ax
        ip <- ip + 2
    | 0x89, 0x4f ->
        write16 mem (bx + (int mem.[ip + 2])) cx
        ip <- ip + 3
    | 0xb9, _ ->
        cx <- read16 mem (ip + 1)
        ip <- ip + 3
    | 0x88, 0x07 ->
        mem.[bx] <- byte ax
        ip <- ip + 2
    | 0x88, 0x67 ->
        mem.[bx + int mem.[ip + 2]] <- byte (ax >>> 8)
        ip <- ip + 3
    | 0xb5, _ ->
        cx <- ((int mem.[ip + 1]) <<< 8) ||| (cx &&& 0xff)
        mem.[bx] <- byte ax
        ip <- ip + 2
    | 0xb1, _ ->
        cx <- (cx &&& 0xff00) ||| (int mem.[ip + 1])
        ip <- ip + 2
    | 0x89, 0x0f ->
        write16 mem bx cx
        ip <- ip + 2
    | 0xc7, 0x06 ->
        write16 mem (read16 mem (ip + 2)) (read16 mem (ip + 4))
        ip <- ip + 6
    | 0xc6, 0x06 ->
        mem.[read16 mem (ip + 2)] <- mem.[ip + 4]
        ip <- ip + 5
    | 0x81, 0x2e ->
        let addr = bx + read16 mem (ip + 2)
        write16 mem addr ((read16 mem addr) - (read16 mem (ip + 4)))
        ip <- ip + 6
    | 0x80, 0x2e ->
        let addr = read16 mem (ip + 2)
        mem.[bx + addr] <- mem.[addr] - mem.[ip + 4]
        ip <- ip + 5
    | 0xba, _ ->
        dx <- read16 mem (ip + 1)
        ip <- ip + 3
    | 0xbc, _ ->
        sp <- read16 mem (ip + 1)
        ip <- ip + 3
    | 0xbd, _ ->
        bp <- read16 mem (ip + 1)
        ip <- ip + 3
    | 0xbe, _ ->
        si <- read16 mem (ip + 1)
        ip <- ip + 3
    | 0xbf, _ ->
        di <- read16 mem (ip + 1)
        ip <- ip + 3
    | 0xcd, 0x07 ->
        match int mem.[ip + 2] with
        | 1 ->
            exit ax
        | 4 ->
            let arg1 = read16 mem (ip + 3)
            let arg2 = read16 mem (ip + 5)
            let bytes = mem.[arg1 .. arg1 + arg2 - 1]
            printf "%s" (System.Text.Encoding.ASCII.GetString bytes)
            ip <- ip + 7
        | sc ->
            printfn "%04x: ??? syscall %d" ip sc
            exit 1
    | 0xcd, n ->
        printfn "%04x: ??? int %x" ip n
        exit 1
    | b, _ ->
        printfn "%04x: %02x ???" ip b
        exit 1
$ 7run regs.out
stack overflow: 0000

でした。