読者です 読者をやめる 読者になる 読者になる

by shigemk2

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

数値をいったんレジスタに入れてからメモリに書き込む #ikebin

UNIX

明日行こうと思って昨日予約しようとしたら中止になっていた……

7shi / ikebin / wiki / pdp11 / write-4 — Bitbucket

わりと先週の復習もかねてる。

アセンブリ

数値を直接メモリに書き込むのが前回だったけど、今回は変数に数値を入れてそれからメモリに書き込む。

/ write(1, hello, 6);
mov $1, r0
sys write
hello
6


/ r1 = hello;
/ r0 = 0x4548;
/ *(uint16_t *)r1 = r0;
mov $hello, r1
mov $42510, r0
mov r0, (r1)

/ write(1, hello, 6);
mov $1, r0
sys write
hello
6


/ r1 = hello;
/ r2 = 0x4c4c;
/ *(uint16_t *)(r1 + 2) = r2;
mov $hello, r1
mov $46114, r2
mov r2, 2(r1)

/ write(1, hello, 6);
mov $1, r0
sys write
hello
6


/ exit(0);
mov $0, r0
sys exit


.data
hello: <hello\n>

逆アセンブラ

機械語から読みやすくするアレ

let aout = System.IO.File.ReadAllBytes "write-4.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 = aout.[16 .. 16 + tsize + dsize - 1]
let mutable pc = 0
let show len dis =
    let words = [ for i in pc .. 2 .. pc + len - 1 -> sprintf "%04x" (read16 mem i) ]
    printfn "%04x: %-14s  %s" pc (String.concat " " words) dis
    pc <- pc + len
while pc < tsize do
    match read16 mem pc with
    | 0x1009 ->
        show 2 "mov r0, (r1)"
    | 0x10b1 ->
        show 4 (sprintf "mov r2, %x(r1)" (read16 mem (pc + 2)))
    | 0x15c0 ->
        show 4 (sprintf "mov $%x, r0" (read16 mem (pc + 2)))
    | 0x15c1 ->
        show 4 (sprintf "mov $%x, r1" (read16 mem (pc + 2)))
    | 0x15c2 ->
        show 4 (sprintf "mov $%x, r2" (read16 mem (pc + 2)))
    | 0x15c9 ->
        show 4 (sprintf "mov $%x, (r1)" (read16 mem (pc + 2)))
    | 0x95f1 ->
        show 6 (sprintf "movb $%x, %x(r1)" (read16 mem (pc + 2)) (read16 mem (pc + 4)))
    | 0x95c9 ->
        show 4 (sprintf "movb $%x, (r1)" (read16 mem (pc + 2)))
    | 0x8901 ->
        show 2 "sys 1 ; exit"
    | 0x8904 ->
        show 2 "sys 4 ; write"
        show 2 "; arg"
        show 2 "; arg"
    | _ ->
        show 2 "???"

インタプリタ

let aout = System.IO.File.ReadAllBytes "write-4.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 = aout.[16 .. 16 + tsize + dsize - 1]

let mutable r0, r1, r2, pc = 0, 0, 0, 0
while pc < tsize do
  match read16 mem pc with
  | 0x1009 ->
    write16 mem r1 r0
    pc <- pc + 2
  | 0x10b1 ->
    write16 mem (r1 + read16 mem (pc + 2)) r2
    pc <- pc + 4
  | 0x15b1 ->
    r0 <- read16 mem (pc + 2)
    pc <- pc + 4
  | 0x15c0 ->
    r0 <- read16 mem (pc + 2)
    pc <- pc + 4
  | 0x15c1 ->
    r1 <- read16 mem (pc + 2)
    pc <- pc + 4
  | 0x15c2 ->
    r2 <- read16 mem (pc + 2)
    pc <- pc + 4
  | 0x15c9 ->
    write16 mem r1 (read16 mem (pc + 2))
    pc <- pc + 4
  | 0x15f1 ->
    write16 mem (r1 + read16 mem (pc + 4)) (read16 mem (pc + 2))
    pc <- pc + 6
  | 0x95c9 ->
    mem.[r1] <- mem.[pc + 2]
    pc <- pc + 4
  | 0x95f1 ->
    mem.[r1 + read16 mem (pc + 4)] <- mem.[pc + 2]
    pc <- pc + 6
  | 0x8901 ->
    exit r0
  | 0x8904 ->
    let arg1 = read16 mem (pc + 2)
    let arg2 = read16 mem (pc + 4)
    let bytes = mem.[arg1 .. arg1 + arg2 - 1]
    printf "%s" (System.Text.Encoding.ASCII.GetString bytes)
    pc <- pc + 6
  | w ->
    printfn "%04x: %04x ???" pc w
    exit 1