更新が非常に空きました。久々にアセンブラです。
%include "stdio.inc" section .bss array0: resb 8 array1: resb 8 flag: resb 1 section .text global start start: mov rcx,flag mov byte [rcx],0 mov rax,1 mov rbx,0 mov rcx,1 call setCell mov rax,2 mov rbx,1 mov rcx,1 call setCell mov rax,0 mov rbx,2 mov rcx,1 call setCell mov rax,1 mov rbx,2 mov rcx,1 call setCell mov rax,2 mov rbx,2 mov rcx,1 call setCell call showMem call NewLine call updateWorld call showMem call NewLine call updateWorld call showMem call NewLine call Exit toggle: push rax push rcx mov rcx,flag mov rax,[rcx] test rax,rax jz .PL0 mov byte [rcx],0 jmp .end .PL0: mov byte [rcx],1 .end: pop rcx pop rax ret ;------ ; set mem ; rax <- idx ; rbx <- val ;------ setMem: push rdx xor rdx,rdx mov rdx,flag mov rdx,[rdx] test rdx,rdx jz .PL0 mov rdx,array0 jmp .body .PL0: mov rdx,array1 .body: push rcx mov rcx,rax mov rax,1 shl rax,cl pop rcx test rbx,rbx jz .off or [rdx],rax jmp .end .off: not rax and [rdx],rax .end: pop rdx ret ;------ ; getMem ; rax <- idx => rax <- val ;------- getMem: push rdx mov rdx,flag mov rdx,[rdx] test rdx,rdx jz .PL0 mov rdx,array0 jmp .body .PL0: mov rdx,array1 .body: mov rdx,[rdx] push rcx mov rcx,rax mov rax,1 shl rax,cl and rdx,rax shr rdx,cl pop rcx mov rax,rdx pop rdx ret showMem: push rcx push rsi mov rcx,64 mov rsi,8 .loop0: dec rcx mov rax,rcx call getMem add rax,'0' call OutChar mov rax,rcx xor rdx,rdx div rsi test rdx,rdx jnz .loop1 call NewLine .loop1: test rcx,rcx jnz .loop0 pop rsi pop rcx ret ;--------- ; getCellIdx ; rax <- x, rbx <- y ; => rax <- idx ;---------- getCellIdx: test rax,rax jns .PL0 add rax,8 .PL0: cmp rax,8 jl .PL1 push rdx push rdi mov rdi,8 xor rdx,rdx div rdi mov rax,rdx pop rdi pop rdx .PL1: test rbx,rbx jns .PL2 add rbx,8 .PL2: cmp rbx,8 jl .PL3 push rdx push rdi push rax mov rdi,8 mov rax,rbx div rdi mov rbx,rdx pop rax pop rdi pop rdx .PL3: push rcx mov rcx,rax mov rax,8 mul rbx add rax,rcx pop rcx ret ;------- ; getCell ; rax <- x ; rbx <- y ; => rax <- data ;-------- getCell: push rbx call getCellIdx pop rbx call getMem ret ;----------- ; Set Cell ; rax <- x, rbx <- y, cl <- val ;----------- setCell: call getCellIdx push rbx mov rbx,rcx call setMem pop rbx ret ;---------- ; Get Living Neighbor cell count ; rax <- x ; rbx <- y ; => rax <- count ;--------- getNeighbor: push rcx push rdi push rsi mov rdi,-1 xor rcx,rcx .loop0: cmp rdi,2 jge .end0 mov rsi,-1 .loop1: cmp rsi,2 jge .end1 cmp rsi,0 jne .body cmp rdi,0 jne .body jmp .bodyend .body: add rax,rdi add rbx,rsi push rax call getCell add rcx,rax pop rax sub rax,rdi sub rbx,rsi .bodyend: inc rsi jmp .loop1 .end1: inc rdi jmp .loop0 .end0: pop rsi pop rdi mov rax,rcx pop rcx ret ;------- ; Update Cell ; rax <- x, rbx <- y ; update cell ;------- updateCell: push rcx mov rcx,rax push rax call getCell test rax,rax jz .dead mov rax,rcx call getNeighbor cmp rax,2 jz .born cmp rax,3 jz .born jmp .death .dead: mov rax,rcx call getNeighbor cmp rax,3 jz .born jmp .death .born: mov rax,rcx push rcx xor rcx,rcx mov rcx,1 call toggle call setCell call toggle pop rcx jmp .end .death: mov rax,rcx push rcx xor rcx,rcx call toggle call setCell call toggle pop rcx .end: pop rax pop rcx ret updateWorld: push rax push rbx xor rax,rax mov rax,7 .loop0: test rax,rax js .end0 xor rbx,rbx mov rbx,7 .loop1: test rbx,rbx js .end1 call updateCell dec rbx jmp .loop1 .end1: dec rax jmp .loop0 .end0: pop rbx pop rax call toggle ret cleanWorld: push rax push rbx xor rax,rax mov rax,7 .loop0: test rax,rax js .end0 xor rbx,rbx mov rbx,7 .loop1: test rbx,rbx js .end1 push rcx xor rcx,rcx call setCell pop rcx dec rbx jmp .loop1 .end1: dec rax jmp .loop0 .end0: pop rbx pop rax call toggle ret
最初は1つのセルを表現するのに、1byteつかうという豪勢なプログラムを書いていたのですが、本来ならば1bitのみでセルの2状態が表現できるので、64マスならば64bitのみで表現できるはずなので、そのように書きなおしました。
64bitサイズだとぴったりレジスタのサイズと同じなので、マップ全体を取得してbit演算するのみセルの状態が取得できます。
64bit分のサイズの値をメモリから読み書きするために毎回伝送するのがどのくらいのコストなのだろうかという事が気になっています。行で取得してから列の分だけシフトした値と演算するようにすれば、伝送する分は8bitで済むので、こちらのほうが速いのだろうかとか考えています。