# ぱらぱらめくる『クヌース本1』

• 64bit マシン
• ２進で64桁
• 16進法では4ビット使う
• 64ビットは16進数(0,1,...,9,a,b,...,f)がで16個並ぶ
# 64桁の01の数値列
a <- sample(0:1,64,replace =TRUE)
# 4桁の01の数値列を0,1,2,...fに対応づける
b <- as.matrix(expand.grid(rep(list(0:1),4)))
b <- b[,4:1]
d <- c(as.character(0:9),letters[1:6])
# 2進64桁を16進16桁に直す
chage64to16<- function(a){
b <- as.matrix(expand.grid(rep(list(0:1),4)))
b <- b[,4:1]
d <- c(as.character(0:9),letters[1:6])
n <- length(a)%/%4
ret <- rep(0,n)
for(i in 1:n){
tmp <- apply((t(b) - a[(1+4*(i-1)):(4*i)]==0),2,prod)
ret[i] <- d[which(tmp==1)]
}
ret
}
chage64to16(a)
a

> chage64to16(a)
[1] "a" "6" "8" "c" "b" "c" "e" "a" "0" "e" "6" "4" "1" "4" "e" "0"
>
> a
[1] 1 0 1 0 0 1 1 0 1 0 0 0 1 1 0 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0
[42] 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 0 0 0

• 文字コードとバイト
• 4ビット→16進数１桁
• 8ビット→16進数２桁→１バイト
• 16ビット→16進数4桁→Unicode UTF-16文字コード→２バイト→１ワイド(wyde)
• 32ビット→16進数8桁→４バイト→２ワイド→１テトラ
• 64ビット→16進数16桁→８バイト→４ワイド→２テトラ→１オクタ
• 非負の整数と正負の整数を表す
seisuu <- function(a,negative =FALSE){
if(negative){
if(a[1] ==1){
sum(a[2:length(a)] * 2^((length(a)-2):0))-2^(length(a)-1)
}else{
sum(a[2:length(a)] * 2^((length(a)-2):0))
}

}else{
sum(a*2^((length(a)-1):0))
}
}

seisuu(rep(1,8))
seisuu(rep(1,8),negative=TRUE)

b <- as.matrix(expand.grid(rep(list(0:1),4)))
b <- b[,4:1]
b

for(i in 1:length(b[,1])){
print(seisuu(b[i,]))
}
for(i in 1:length(b[,1])){
print(seisuu(b[i,],negative=TRUE))
}

> b
Var4 Var3 Var2 Var1
[1,]    0    0    0    0
[2,]    0    0    0    1
[3,]    0    0    1    0
[4,]    0    0    1    1
[5,]    0    1    0    0
[6,]    0    1    0    1
[7,]    0    1    1    0
[8,]    0    1    1    1
[9,]    1    0    0    0
[10,]    1    0    0    1
[11,]    1    0    1    0
[12,]    1    0    1    1
[13,]    1    1    0    0
[14,]    1    1    0    1
[15,]    1    1    1    0
[16,]    1    1    1    1
> for(i in 1:length(b[,1])){
+ print(seisuu(b[i,]))
+ }
[1] 0
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
> for(i in 1:length(b[,1])){
+ print(seisuu(b[i,],negative=TRUE))
+ }
[1] 0
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] -8
[1] -7
[1] -6
[1] -5
[1] -4
[1] -3
[1] -2
[1] -1

• メモリとレジスタ
• メモリ
• M[0],...,M[2^64-1]個のメモリセルからなるメモリ。全部でバイトのメモリに相当する
• レジスタ
• メモリのグルーピング
• (M[0],M[1]),...,(M[2k],M[2k+1]),...と組にして、それぞれに１ワイドを対応させる(個のワイドができる
• ,
• となり合う4個を束ねて個のテトラができる
• となり合う8個を束ねて個のオクタができる
• を含むワイド・テトラ・オクタとする
• の場合は
p <- 10
M <- sample(0:1,2^p,replace=TRUE)
t <- 8 # オクタ

x <- sample(0:(2^p/t),1)
y <- floor(x/t)

M8 <- M[(t*y):(t*y+t-1)]
x
y
M[(x-t):(x+t)]
M8

> x
[1] 60
> y
[1] 7
> M[(x-t):(x+t)]
[1] 1 0 1 1 0 1 0 1 0 0 1 0 0 0 1 1 1
> M8
[1] 0 1 0 1 0 0 1 0
> M[56]
[1] 0
> M[56:63]
[1] 0 1 0 1 0 0 1 0

• コマンド
• メモリに入れる
• １コマンドは１テトラバイト
• １テトラバイトを構成する４バイトはそれぞれOP,X,Y,Zに対応する
• OPはオペレーションコード
• X,Y,Zはオペランド
• 命令(256種類)
• 命令は分類される
• ロードとストア
• ロードとストア
• ロードはメモリからレジスタへの書きだし、ストアはレジスタからメモリへの書きこみ
• 書きだし・書き込みにあたって、バイト・ワイド・テトラ・オクタの４つの長さで別々にできるようにし、また、符号付きか符号なしか、(バイト・ワイド・テトラだと桁に余裕があるが)右詰にするか左詰にするか、などで、それぞれ異なる命令として決めてある
• 数値演算命令
• レジスタの値とレジスタの値をとって演算結果を納める
• 加減乗除、剰余、加算は少しバリエーションあり、符号反転、左右へシフト、大小比較
• 条件命令
• レジスタの値の正負ゼロを判定して、その判定結果によって、納める値を変える
• ビットごと命令
• 64個のビットのビットごと演算(ブール演算)(参考)
• バイトごと・ワイドごと・テトラごと・オクタごと命令
• ビットごとの代わりにバイト・ワイド・テトラ・オクタごとでも
• オクタバイトは8x8のブール行列と見ることもできる
• 浮動小数点演算命令
• 即値命令
• 良く使う「値(1やバイト・ワイド…などでの桁変更、真偽値など)」の扱いは命令として使えるようにしてある
• メモリへのアクセスを発生させないで命令が実行できる
• ジャンプと分岐の命令
• 指定がないときの命令の実行順は(OP1,X1,Y1,Z1),(OP2,X2,Y2,Z2),...のような並び順でOP1,OP2の命令がそれぞれのオペランドに対して行われるが、それを変えたいときに使う
• 分岐処理は、条件判定をしてから分岐先のことを考えるやり方と、条件判定をする前から、分岐するものと見込んで準備しておく(外れたら、見込み作業は捨てる)方法がある。分岐予測(Wiki)という
• これに対応して、予測ありの分岐と予測なしの分岐の２通りの命令が準備されている
• サブルーチンコール命令
• システムとのやりとりのための命令
• 割り込み命令
• 全256コマンド表はこちら
• この表の見方は：表の行の"nx"の"n"が16進数で、"x"の方に列の方の値を対応づける。ただし列は８列になっていて、２段で8x2=16進数に対応。上段は0,1,...,7で、下段だったら、8,9,a,...,f
• したがって、左上隅のTRAPは"00"、その隣のFCMPは"01"、#Exの行の#3の列の上段はSETLだが、これは、"E3"で、その下のORLは"EB"
• 命令は専用レジスタを使って処理をする
• アセンブラ
• サブルーチンとコルーチン
• インタープリタ