Comment detail

変形Fizz-Buzz問題 (Nested Flatten)

Mac OS X (PowerPC 32bit) アセンブリで。else if, elseの文法自体ないんで普通に。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
        ;; 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

fizz_len, buzz_len, hoge_len は演算する必要ありませんでした。全部4でOK。

Index

Feed

Other

Link

Pathtraq

loading...