diff --git a/Makefile b/Makefile index d3034e3..427b6ae 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,8 @@ -all: build run +all: mp4 + +gif: build run convert-gif clean + +mp4: build run convert-mp4 clean build: nasm -f elf64 main.s -o main.o @@ -7,4 +11,13 @@ build: run: ./gen -.PHONY: all build run +convert-gif: + convert -delay 8 -loop 0 output-*.ppm output.gif + +convert-mp4: + ffmpeg -i output-%02d.ppm -r 60 output.mp4 + +clean: + rm -rf output-*.ppm + +.PHONY: all gif mp4 build run convert-gif convert-mp4 clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..b20bc11 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# ASMアニメーション作成 +10分で作ったお遊びプロジェクトで、チェッカーボードを60回生成してからアニメーションに変換する物です。\ +完全にx64アセンブリでFreeBSD向けに書きました。\ +Linuxを使っている人は、システムコール番号だけ変更すれば大丈夫です。\ +其れ以外は同じ様に動くはずです。\ +但し、実際にテストしたのはFreeBSDのみです。 + +![](output.gif) diff --git a/main.s b/main.s index 55d3ac3..97abce5 100644 --- a/main.s +++ b/main.s @@ -8,12 +8,13 @@ default rel section .data section .rodata - outfile db "output.ppm", 0 + basename db "output-",0 + suffix db ".ppm", 0 hdr db "P6", 10, "960 540", 10, "255", 10 err db "開くに失敗", 10 errlen equ $-err - suc db "画像を「output.ppm」に出力しました。", 10 + suc db "60フレームを作成しました。", 10 suclen equ $-suc w equ 960 @@ -21,11 +22,35 @@ section .rodata section .bss buf resb 960*540*3 + outfile resb 64 ; "output-nn.ppm\0" section .text global _start _start: + mov r12, 0 ; i = 0 + +frameloop: + ; ファイル名 + lea rdi, [outfile] + lea rsi, [basename] + call strcpy + + ; iは2つの文字に変換 + mov rax, r12 + mov rcx, 10 + xor rdx, rdx + div rcx ; rax = 10, rdx = 01 + + add al, '0' + add dl, '0' + mov [rdi], al ; 10 + mov [rdi+1], dl; 01 + add rdi, 2 + + lea rsi, [suffix] + call strcpy ; 「.ppm\0」の追加 + mov rax, 5 ; sys_openat lea rdi, [outfile] mov rsi, 0x100601 ; 0x100601 = 0001 0000 0000 0110 0000 0001 = 1048576 + 1024 + 512 + 1 = 1050113 @@ -51,26 +76,31 @@ _start: ; チェッカーボードループ lea rdi, [buf] mov rcx, h + xor r13, r13 yloop: mov r8d, w xloop: ; (x/60 + y/60) % 2の計算 - mov eax, r8d + mov eax, r8d ; x + add eax, r12d ; x + i xor edx, edx mov ebx, 60 - div ebx ; eax = x/60 + div ebx ; eax = (x + i)/60 push rax - mov eax, ecx + mov eax, r13d + add eax, r12d ; y + i xor edx, edx - div ebx ; eax = y/60 + div ebx ; eax = (y + i)/60 + pop rdx - add eax, edx ; x/60 + y/60 + add eax, edx ; (x + i)/60 + (y + i)/60 and al, 1 ; % 2 jz .black +.green: mov al, 0 stosb ; R mov al, 0xFF @@ -88,7 +118,10 @@ xloop: .next: dec r8d jnz xloop - loop yloop ; dec rcx, jnz yloop + + inc r13d + dec rcx + jnz yloop ; ピクセルデータの書き込み mov eax, 4 @@ -97,17 +130,21 @@ xloop: mov edx, 960*540*3 syscall +close: + mov rax, 6 ; sys_close + mov rdi, r15 + syscall + + inc r12 + cmp r12, 60 + jb frameloop + mov rax, 4 mov rdi, 1 lea rsi, [suc] mov rdx, suclen syscall -close: - mov rax, 6 ; sys_close - mov rdi, r15 - syscall - end: mov eax, 1 ; sys_exit xor edi, edi @@ -123,3 +160,16 @@ error: mov rax, 1 mov rdi, 1 syscall + +strcpy: +.loop: + mov al, [rsi] + mov [rdi], al + test al, al + jz .done + inc rdi + inc rsi + jmp .loop + +.done: + ret diff --git a/output.gif b/output.gif new file mode 100644 index 0000000..db0ee10 Binary files /dev/null and b/output.gif differ