ビット演算

NScripterでビット演算を(無理矢理)やってみる。
ていうか、ビット演算自体を知らない人は、NScripterユーザーの中には多いんだろうな。

追加した命令

  • and
  • nand
  • or
  • nor
  • xor
  • xnor

ここまで、全て同じ形式で記述する。すなわち、

and %result,%a,%b
  • not

これだけは、

not %result,%a

の形で記述する。
もし、少しでも速度を求めたいなら、

num2bit $result,%num

で数値を$resultの中に内部形式に変換して格納した後、

  • bit_and
  • bit_nand
  • bit_or
  • bit_nor
  • bit_xor
  • bit_xnor
  • bit_not

(記述形式は数値変数が文字列変数に変わっただけで全て同じ)
で扱い、

bit2num %num,$result

で、元の数値に戻せる。
また、ビットシフト演算も可能。

lshift
左ビットシフト演算
rshift
右ビットシフト演算(算術)
rshift_logical
右ビットシフト演算(論理)

そしてこれらに対しても、内部形式での対応命令がある。

  • bit_lshift
  • bit_rshift
  • bit_rshift_logical

さあ、これで思う様ビット演算をやりまくれ!

define節以下game以上

mov %0,100 ; お好みで
numalias num2bit_bit,%0:inc %0
numalias num2bit_num,%0:inc %0
numalias num2bit_loop,%0:inc %0
numalias num2bit_sgn,%0:inc %0
numalias num2bit_letter,%0:inc %0

numalias bit_result,%0:inc %0
numalias bit_a,%0:inc %0
numalias bit_b,%0:inc %0
numalias bit_lettera,%0:inc %0
numalias bit_letterb,%0:inc %0
numalias bit_letter,%0:inc %0
numalias bit_loop,%0:inc %0

numalias bit_aa,%0:inc %0
numalias bit_bb,%0:inc %0
numalias bit_cc,%0:inc %0

defsub num2bit
defsub bit2num
defsub bit_and
defsub bit_nand
defsub bit_or
defsub bit_nor
defsub bit_xor
defsub bit_xnor
defsub bit_not
defsub bit_lshift
defsub bit_rshift
defsub bit_rshift_logical
defsub and
defsub nand
defsub or
defsub nor
defsub xor
defsub xnor
defsub not
defsub lshift
defsub rshift
defsub rshift_logical

game以下start節以上

;==================
; num2bit
;==================
; 数値を、2進数の文字列に変換する。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変換したい数値
*num2bit
getparam s%num2bit_bit,%num2bit_num
if %num2bit_num=0 mov %num2bit_sgn,0:jumpf
if %num2bit_num<0 mov %num2bit_sgn,-1:jumpf
if %num2bit_num>0 mov %num2bit_sgn,1
~
mul %num2bit_num,%num2bit_sgn
mov $%num2bit_bit,""
for %num2bit_loop=1 to 31
	if %num2bit_num=0 mov $num2bit_letter,"0":jumpf
	mov %num2bit_letter,%num2bit_num mod 2
	div %num2bit_num,2
	itoa $num2bit_letter,%num2bit_letter
~
	mov $%num2bit_bit,$num2bit_letter+$%num2bit_bit
next
mov $%num2bit_bit,"0"+$%num2bit_bit
if %num2bit_sgn=-1 bit_not $%num2bit_bit,$%num2bit_bit
return

;==================
; bit2num
;==================
; 数値を、2進数の文字列に変換する。
; 第一引数:結果を受け取る数値変数
; 第二引数:変換したい文字列
*bit2num
getparam i%num2bit_num,$num2bit_bit
mid $num2bit_sgn,$num2bit_bit,0,1
if $num2bit_sgn="1" bit_not $num2bit_bit,$num2bit_bit
mov %%num2bit_num,0
for %num2bit_loop=1 to 31
	mul %%num2bit_num,2
	mid $num2bit_letter,$num2bit_bit,%num2bit_loop,1
	if $num2bit_letter="1" inc %%num2bit_num
next
if $num2bit_sgn="1" mul %%num2bit_num,-1
return

;==================
; bit_and
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_and
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera="1" && $bit_letterb="1" mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_nand
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_nand
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera="1" && $bit_letterb="1" mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_or
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_or
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera="0" && $bit_letterb="0" mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_nor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_nor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera="0" && $bit_letterb="0" mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_xor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_xor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera=$bit_letterb mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_xnor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_xnor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera=$bit_letterb mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_not
;==================
; 2進数(32桁限定)のビットを反転させる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:反転させたい文字列変数
*bit_not
getparam s%bit_result,$bit_a
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	if $bit_lettera="0" add $%bit_result,"1"
	if $bit_lettera="1" add $%bit_result,"0"
next
return

;==================
; bit_lshift
;==================
; ビットを左に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_lshift
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
mid $%bit_result,$bit_a,%bit_a-1,32-%bit_a
for %bit_loop=1 to %bit_a
	add $%bit_result,"0"
next
return

;==================
; bit_rshift
;==================
; ビットを右に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_rshift
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
mid $bit_letter,$bit_a,0,1
for %bit_loop=1 to %bit_a+1
	add $%bit_result,$bit_letter
next
mid $bit_lettera,$bit_a,1,31-%bit_a
add $%bit_result,$bit_lettera
return

;==================
; bit_rshift_logical
;==================
; ビットを右に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_rshift_logical
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
for %bit_loop=1 to %bit_a
	add $%bit_result,"0"
next
mid $bit_lettera,$bit_a,0,32-%bit_a
add $%bit_result,$bit_lettera
return

;==================
; and
;==================
; 数値変数をビット演算する。and
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*and
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_and $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; nand
;==================
; 数値変数をビット演算する。nand
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*nand
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_nand $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; or
;==================
; 数値変数をビット演算する。or
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*or
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_or $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; nor
;==================
; 数値変数をビット演算する。nor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*nor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_nor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; xor
;==================
; 数値変数をビット演算する。xor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*xor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_xor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; xnor
;==================
; 数値変数をビット演算する。xnor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*xnor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_xnor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; not
;==================
; 数値変数をビット演算する。not
; 第一引数:結果を受け取る引数
; 第二引数:反転させる数値
*not
getparam i%bit_cc,%bit_aa
num2bit $bit_aa,%bit_aa
not $bit_cc,$bit_aa
bit_bit2num %%bit_cc,$bit_cc
return

;==================
; lshift
;==================
; 数値変数をビット演算する。lshift
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*lshift
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_lshift $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; rshift
;==================
; 数値変数をビット演算する。rshift
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*rshift
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_rshift $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; rshift_logical
;==================
; 数値変数をビット演算する。rshift_logical
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*rshift_logical
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_rshift_logical $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

考えること

色々とNScripterを使ってやってますが、きっと楽しいのは本人だけなんじゃないかと思うことがある。
seteffectspeed命令(1) : 幻惑郷みたいな記事の方が、きっと即席で人の役に立つんだろうなとうらやましくなる。

ビット演算

NScripterでビット演算を(無理矢理)やってみる。
ていうか、ビット演算自体を知らない人は、NScripterユーザーの中には多いんだろうな。

追加した命令

  • and
  • nand
  • or
  • nor
  • xor
  • xnor

ここまで、全て同じ形式で記述する。すなわち、

and %result,%a,%b
  • not

これだけは、

not %result,%a

の形で記述する。
もし、少しでも速度を求めたいなら、

num2bit $result,%num

で数値を$resultの中に内部形式に変換して格納した後、

  • bit_and
  • bit_nand
  • bit_or
  • bit_nor
  • bit_xor
  • bit_xnor
  • bit_not

(記述形式は数値変数が文字列変数に変わっただけで全て同じ)
で扱い、

bit2num %num,$result

で、元の数値に戻せる。
また、ビットシフト演算も可能。

lshift
左ビットシフト演算
rshift
右ビットシフト演算(算術)
rshift_logical
右ビットシフト演算(論理)

そしてこれらに対しても、内部形式での対応命令がある。

  • bit_lshift
  • bit_rshift
  • bit_rshift_logical

さあ、これで思う様ビット演算をやりまくれ!

define節以下game以上

mov %0,100 ; お好みで
numalias num2bit_bit,%0:inc %0
numalias num2bit_num,%0:inc %0
numalias num2bit_loop,%0:inc %0
numalias num2bit_sgn,%0:inc %0
numalias num2bit_letter,%0:inc %0

numalias bit_result,%0:inc %0
numalias bit_a,%0:inc %0
numalias bit_b,%0:inc %0
numalias bit_lettera,%0:inc %0
numalias bit_letterb,%0:inc %0
numalias bit_letter,%0:inc %0
numalias bit_loop,%0:inc %0

numalias bit_aa,%0:inc %0
numalias bit_bb,%0:inc %0
numalias bit_cc,%0:inc %0

defsub num2bit
defsub bit2num
defsub bit_and
defsub bit_nand
defsub bit_or
defsub bit_nor
defsub bit_xor
defsub bit_xnor
defsub bit_not
defsub bit_lshift
defsub bit_rshift
defsub bit_rshift_logical
defsub and
defsub nand
defsub or
defsub nor
defsub xor
defsub xnor
defsub not
defsub lshift
defsub rshift
defsub rshift_logical

game以下start節以上

;==================
; num2bit
;==================
; 数値を、2進数の文字列に変換する。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変換したい数値
*num2bit
getparam s%num2bit_bit,%num2bit_num
if %num2bit_num=0 mov %num2bit_sgn,0:jumpf
if %num2bit_num<0 mov %num2bit_sgn,-1:jumpf
if %num2bit_num>0 mov %num2bit_sgn,1
~
mul %num2bit_num,%num2bit_sgn
mov $%num2bit_bit,""
for %num2bit_loop=1 to 31
	if %num2bit_num=0 mov $num2bit_letter,"0":jumpf
	mov %num2bit_letter,%num2bit_num mod 2
	div %num2bit_num,2
	itoa $num2bit_letter,%num2bit_letter
~
	mov $%num2bit_bit,$num2bit_letter+$%num2bit_bit
next
mov $%num2bit_bit,"0"+$%num2bit_bit
if %num2bit_sgn=-1 bit_not $%num2bit_bit,$%num2bit_bit
return

;==================
; bit2num
;==================
; 数値を、2進数の文字列に変換する。
; 第一引数:結果を受け取る数値変数
; 第二引数:変換したい文字列
*bit2num
getparam i%num2bit_num,$num2bit_bit
mid $num2bit_sgn,$num2bit_bit,0,1
if $num2bit_sgn="1" bit_not $num2bit_bit,$num2bit_bit
mov %%num2bit_num,0
for %num2bit_loop=1 to 31
	mul %%num2bit_num,2
	mid $num2bit_letter,$num2bit_bit,%num2bit_loop,1
	if $num2bit_letter="1" inc %%num2bit_num
next
if $num2bit_sgn="1" mul %%num2bit_num,-1
return

;==================
; bit_and
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_and
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera="1" && $bit_letterb="1" mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_nand
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_nand
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera="1" && $bit_letterb="1" mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_or
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_or
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera="0" && $bit_letterb="0" mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_nor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_nor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera="0" && $bit_letterb="0" mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_xor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_xor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera=$bit_letterb mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_xnor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_xnor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera=$bit_letterb mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_not
;==================
; 2進数(32桁限定)のビットを反転させる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:反転させたい文字列変数
*bit_not
getparam s%bit_result,$bit_a
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	if $bit_lettera="0" add $%bit_result,"1"
	if $bit_lettera="1" add $%bit_result,"0"
next
return

;==================
; bit_lshift
;==================
; ビットを左に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_lshift
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
mid $%bit_result,$bit_a,%bit_a-1,32-%bit_a
for %bit_loop=1 to %bit_a
	add $%bit_result,"0"
next
return

;==================
; bit_rshift
;==================
; ビットを右に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_rshift
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
mid $bit_letter,$bit_a,0,1
for %bit_loop=1 to %bit_a+1
	add $%bit_result,$bit_letter
next
mid $bit_lettera,$bit_a,1,31-%bit_a
add $%bit_result,$bit_lettera
return

;==================
; bit_rshift_logical
;==================
; ビットを右に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_rshift_logical
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
for %bit_loop=1 to %bit_a
	add $%bit_result,"0"
next
mid $bit_lettera,$bit_a,0,32-%bit_a
add $%bit_result,$bit_lettera
return

;==================
; and
;==================
; 数値変数をビット演算する。and
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*and
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_and $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; nand
;==================
; 数値変数をビット演算する。nand
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*nand
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_nand $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; or
;==================
; 数値変数をビット演算する。or
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*or
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_or $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; nor
;==================
; 数値変数をビット演算する。nor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*nor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_nor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; xor
;==================
; 数値変数をビット演算する。xor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*xor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_xor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; xnor
;==================
; 数値変数をビット演算する。xnor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*xnor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_xnor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; not
;==================
; 数値変数をビット演算する。not
; 第一引数:結果を受け取る引数
; 第二引数:反転させる数値
*not
getparam i%bit_cc,%bit_aa
num2bit $bit_aa,%bit_aa
not $bit_cc,$bit_aa
bit_bit2num %%bit_cc,$bit_cc
return

;==================
; lshift
;==================
; 数値変数をビット演算する。lshift
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*lshift
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_lshift $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; rshift
;==================
; 数値変数をビット演算する。rshift
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*rshift
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_rshift $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; rshift_logical
;==================
; 数値変数をビット演算する。rshift_logical
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*rshift_logical
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_rshift_logical $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

ビット演算

NScripterでビット演算を(無理矢理)やってみる。
ていうか、ビット演算自体を知らない人は、NScripterユーザーの中には多いんだろうな。

追加した命令

  • and
  • nand
  • or
  • nor
  • xor
  • xnor

ここまで、全て同じ形式で記述する。すなわち、

and %result,%a,%b
  • not

これだけは、

not %result,%a

の形で記述する。
もし、少しでも速度を求めたいなら、

num2bit $result,%num

で数値を$resultの中に内部形式に変換して格納した後、

  • bit_and
  • bit_nand
  • bit_or
  • bit_nor
  • bit_xor
  • bit_xnor
  • bit_not

(記述形式は数値変数が文字列変数に変わっただけで全て同じ)
で扱い、

bit2num %num,$result

で、元の数値に戻せる。
また、ビットシフト演算も可能。

lshift
左ビットシフト演算
rshift
右ビットシフト演算(算術)
rshift_logical
右ビットシフト演算(論理)

そしてこれらに対しても、内部形式での対応命令がある。

  • bit_lshift
  • bit_rshift
  • bit_rshift_logical

さあ、これで思う様ビット演算をやりまくれ!

define節以下game以上

mov %0,100 ; お好みで
numalias num2bit_bit,%0:inc %0
numalias num2bit_num,%0:inc %0
numalias num2bit_loop,%0:inc %0
numalias num2bit_sgn,%0:inc %0
numalias num2bit_letter,%0:inc %0

numalias bit_result,%0:inc %0
numalias bit_a,%0:inc %0
numalias bit_b,%0:inc %0
numalias bit_lettera,%0:inc %0
numalias bit_letterb,%0:inc %0
numalias bit_letter,%0:inc %0
numalias bit_loop,%0:inc %0

numalias bit_aa,%0:inc %0
numalias bit_bb,%0:inc %0
numalias bit_cc,%0:inc %0

defsub num2bit
defsub bit2num
defsub bit_and
defsub bit_nand
defsub bit_or
defsub bit_nor
defsub bit_xor
defsub bit_xnor
defsub bit_not
defsub bit_lshift
defsub bit_rshift
defsub bit_rshift_logical
defsub and
defsub nand
defsub or
defsub nor
defsub xor
defsub xnor
defsub not
defsub lshift
defsub rshift
defsub rshift_logical

game以下start節以上

;==================
; num2bit
;==================
; 数値を、2進数の文字列に変換する。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変換したい数値
*num2bit
getparam s%num2bit_bit,%num2bit_num
if %num2bit_num=0 mov %num2bit_sgn,0:jumpf
if %num2bit_num<0 mov %num2bit_sgn,-1:jumpf
if %num2bit_num>0 mov %num2bit_sgn,1
~
mul %num2bit_num,%num2bit_sgn
mov $%num2bit_bit,""
for %num2bit_loop=1 to 31
	if %num2bit_num=0 mov $num2bit_letter,"0":jumpf
	mov %num2bit_letter,%num2bit_num mod 2
	div %num2bit_num,2
	itoa $num2bit_letter,%num2bit_letter
~
	mov $%num2bit_bit,$num2bit_letter+$%num2bit_bit
next
mov $%num2bit_bit,"0"+$%num2bit_bit
if %num2bit_sgn=-1 bit_not $%num2bit_bit,$%num2bit_bit
return

;==================
; bit2num
;==================
; 数値を、2進数の文字列に変換する。
; 第一引数:結果を受け取る数値変数
; 第二引数:変換したい文字列
*bit2num
getparam i%num2bit_num,$num2bit_bit
mid $num2bit_sgn,$num2bit_bit,0,1
if $num2bit_sgn="1" bit_not $num2bit_bit,$num2bit_bit
mov %%num2bit_num,0
for %num2bit_loop=1 to 31
	mul %%num2bit_num,2
	mid $num2bit_letter,$num2bit_bit,%num2bit_loop,1
	if $num2bit_letter="1" inc %%num2bit_num
next
if $num2bit_sgn="1" mul %%num2bit_num,-1
return

;==================
; bit_and
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_and
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera="1" && $bit_letterb="1" mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_nand
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_nand
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera="1" && $bit_letterb="1" mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_or
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_or
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera="0" && $bit_letterb="0" mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_nor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_nor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera="0" && $bit_letterb="0" mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_xor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_xor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera=$bit_letterb mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_xnor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_xnor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera=$bit_letterb mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_not
;==================
; 2進数(32桁限定)のビットを反転させる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:反転させたい文字列変数
*bit_not
getparam s%bit_result,$bit_a
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	if $bit_lettera="0" add $%bit_result,"1"
	if $bit_lettera="1" add $%bit_result,"0"
next
return

;==================
; bit_lshift
;==================
; ビットを左に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_lshift
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
mid $%bit_result,$bit_a,%bit_a-1,32-%bit_a
for %bit_loop=1 to %bit_a
	add $%bit_result,"0"
next
return

;==================
; bit_rshift
;==================
; ビットを右に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_rshift
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
mid $bit_letter,$bit_a,0,1
for %bit_loop=1 to %bit_a+1
	add $%bit_result,$bit_letter
next
mid $bit_lettera,$bit_a,1,31-%bit_a
add $%bit_result,$bit_lettera
return

;==================
; bit_rshift_logical
;==================
; ビットを右に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_rshift_logical
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
for %bit_loop=1 to %bit_a
	add $%bit_result,"0"
next
mid $bit_lettera,$bit_a,0,32-%bit_a
add $%bit_result,$bit_lettera
return

;==================
; and
;==================
; 数値変数をビット演算する。and
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*and
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_and $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; nand
;==================
; 数値変数をビット演算する。nand
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*nand
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_nand $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; or
;==================
; 数値変数をビット演算する。or
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*or
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_or $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; nor
;==================
; 数値変数をビット演算する。nor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*nor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_nor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; xor
;==================
; 数値変数をビット演算する。xor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*xor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_xor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; xnor
;==================
; 数値変数をビット演算する。xnor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*xnor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_xnor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; not
;==================
; 数値変数をビット演算する。not
; 第一引数:結果を受け取る引数
; 第二引数:反転させる数値
*not
getparam i%bit_cc,%bit_aa
num2bit $bit_aa,%bit_aa
not $bit_cc,$bit_aa
bit_bit2num %%bit_cc,$bit_cc
return

;==================
; lshift
;==================
; 数値変数をビット演算する。lshift
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*lshift
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_lshift $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; rshift
;==================
; 数値変数をビット演算する。rshift
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*rshift
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_rshift $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; rshift_logical
;==================
; 数値変数をビット演算する。rshift_logical
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*rshift_logical
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_rshift_logical $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return