;; Mac OS X (PowerPC 32bit) ;; % as -o fizzbuzz.o fizzbuzz.s && gcc fizzbuzz.o -o fizzbuzz .machine ppc .globl _main _main: li r6, 1 ; 行番号 _print_line: li r9, 0 ; Fizz出力フラグ ;; 行番号の出力 li r4, hi16(line) addi r4, r4, lo16(line) li r5, hi16(line_len) addi r5, r5, lo16(line_len) ;; 行番号の xx を書き換える cmpli cr7, r6, 10 blt cr7, _replace_one_digit ;; 二桁の行番号 ;; 一桁目を求める li r8, 10 ; 10で割った商を求める divwu r7, r6, r8 addi r7, r7, 48 ; 数字のASCIIコードを求める stb r7, 0(r4) ; 文字列の先頭を書き換える addi r4, r4, 1 ; 文字列のポインタを進める ;; 二桁目を求める li r8, 10 ; 10で割った余りを求める divwu r7, r6, r8 ; 割って(=商) mullw r7, r7, r8 ; かけて(商*除数) subf r7, r7, r6 ; 引く(被除数-商*除数) addi r7, r7, 48 ; 数字のASCIIコードを求める stb r7, 0(r4) ; 文字列の先頭を書き換える subi r4, r4, 1 ; 文字列のポインタを戻しておく b _print_line_num _replace_one_digit: li r7, 32 ; ASCIIコード: ' ' stb r7, 0(r4) addi r4, r4, 1 addi r7, r6, 48 ; 数字のASCIIコードを求める stb r7, 0(r4) subi r4, r4, 1 ; 文字列のポインタを戻しておく _print_line_num: bl _print_str _print_msg: ;; 3の倍数 li r8, 3 divwu r7, r6, r8 mullw r7, r7, r8 subf r7, r7, r6 cmpli cr7, r7, 0 bne cr7, _print_msg2 ;; Fizz を出力 li r9, 1 ; Fizz出力済みフラグ li r4, hi16(fizz) addi r4, r4, lo16(fizz) li r5, hi16(fizz_len) addi r5, r5, lo16(fizz_len) bl _print_str _print_msg2: ;; 5の倍数 li r8, 5 divwu r7, r6, r8 mullw r7, r7, r8 subf r7, r7, r6 cmpli cr7, r7, 0 bne cr7, _print_hoge ;; Buzz を出力 li r4, hi16(buzz) addi r4, r4, lo16(buzz) li r5, hi16(buzz_len) addi r5, r5, lo16(buzz_len) bl _print_str b _print_term _print_hoge: ;; Fizz を出力済みなら飛ばす cmpli cr7, r9, 0 bne cr7, _print_term ;; hoge を出力 li r4, hi16(hoge) addi r4, r4, lo16(hoge) li r5, hi16(hoge_len) addi r5, r5, lo16(hoge_len) bl _print_str _print_term: ;; 改行の出力 li r4, hi16(lf) addi r4, r4, lo16(lf) li r5, hi16(lf_len) addi r5, r5, lo16(lf_len) bl _print_str ;; 20行分繰り返す addi r6, r6, 1 cmpli cr7, r6, 20 ble cr7, _print_line b _exit ;; 文字列を出力する ;; r4 に文字列のアドレスを、r5 に文字列の長さをセットしておく _print_str: ;; スタックに退避 stwu r6, -4(r1) ;; sys_write() li r3, 1 ; 標準出力 li r0, 4 ; sys_write sc ; 呼び出し ;; スタックから復帰 lwz r6, 0(r1) addi r1, r1, 4 ;; サブルーチンから戻る blr _exit: li r3, 0 li r0, 1 ; sys_exit sc .data .align 2 line: ;; xx の箇所は出力時に書き換える .asciz "xx: " line_len = 4 fizz: .asciz "Fizz" fizz_len = . - fizz - 1 buzz: .asciz "Buzz" buzz_len = . - buzz - 1 hoge: .asciz "hoge" hoge_len = . - hoge - 1 lf: .asciz "\n" lf_len = 1