Comment detail

文字列の均等分割 (Nested Flatten)

Mac OS X (PowerPC 32bit) アセンブリで。文字列を指定された行数で区切り、区切った回数を一行の文字数とする方法で。

  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
;; ------------------------------------------------
;; strsplit.s for Mac OS X (PowerPC 32bit)
;; % as -o strsplit.o strsplit.s
;; ------------------------------------------------

        .machine ppc
        .globl  _main

;;
;; r6: 均等分割する行数
;; r7: 均等分割する文字列
;; r8: 一行の文字列数
;; r9: 一行の文字列数が r8 より少なくなる行
;;
_main:
        ;; 初期化
        li      r6, 4           ; 適当な値
        lis     r7, hi16(line)
        addi    r7, r7, lo16(line)
        li      r8, 1
        li      r9, 0

_count_init:
        mr      r3, r7          ; カウント用に文字列ポインタをコピー
        li      r4, 0           ; カウント
        
_count:
        ;; 2バイト決め打ち
        lbz     r0, 0(r3)
        cmpli   cr7, r0, 0      ; 文字列の終端
        beq     cr7, _count_end
        addi    r3, r3, 2
        addi    r4, r4, 1
        cmpl    cr7, r4, r6
        blt     cr7, _count

        li      r4, 0           ; 行数をクリア
        addi    r8, r8, 1
        b       _count

_count_end:
        mr      r9, r4          ; 文字数が少なくなる行のセット

_print:
        lis     r4, ha16(temp)
        addi    r4, r4, lo16(temp)
        mr      r2, r8          ; 一行の残り文字数

_print_char:
        ;; スタックに退避
        stwu    r2, -4(r1)
        stwu    r4, -4(r1)
        stwu    r6, -4(r1)
        stwu    r7, -4(r1)
        stwu    r8, -4(r1)
        stwu    r9, -4(r1)

        ;; 一文字ずつ temp にコピーして出力
        lbz     r0, 0(r7)       ; r0: 文字コピー用
        cmpli   cr7, r0, 0
        beq     cr7, _exit
        stb     r0, 0(r4)
        lbz     r0, 1(r7)
        stb     r0, 1(r4)
        li      r3, 1           ; stdout
        li      r5, 2
        li      r0, 4           ; sys_write
        sc                      ; system call

        ;; スタックから復帰
        lwz     r9, 0(r1)
        lwzu    r8, 4(r1)
        lwzu    r7, 4(r1)
        lwzu    r6, 4(r1)
        lwzu    r4, 4(r1)
        lwzu    r2, 4(r1)
        addi    r1, r1, 4
        
        ;; 次のループの処理
        addi    r7, r7, 2       ; 2バイト
        subi    r2, r2, 1

        ;; 折り返しの判断
        cmplw   cr7, r6, r9     ; r6 <= r9  cr7[lt,eq]=1
        cmplwi  cr6, r2, 1      ; r2 == 1   cr6[eq]=1
        cror    2, 28, 30       ; cr0[eq] = cr7[lt] | cr7[eq]
        crand   2, 2, 26        ; cr0[eq] = cr0[eq] & cr6[eq]
        beq     cr0, _print_turn
        cmpli   cr7, r2, 0
        bgt     cr7, _print_char

_print_turn:
        ;; 折り返し地点
        mr      r2, r8          ; 一行の残り文字数をクリア
        subi    r6, r6, 1

        ;; スタックに退避
        stwu    r2, -4(r1)
        stwu    r4, -4(r1)
        stwu    r6, -4(r1)
        stwu    r7, -4(r1)
        stwu    r8, -4(r1)
        stwu    r9, -4(r1)

        bl      _print_lf

        ;; スタックから復帰
        lwz     r9, 0(r1)
        lwzu    r8, 4(r1)
        lwzu    r7, 4(r1)
        lwzu    r6, 4(r1)
        lwzu    r4, 4(r1)
        lwzu    r2, 4(r1)
        addi    r1, r1, 4

        b       _print_char

;; 改行の出力
_print_lf:
        mflr    r2              ; リンクレジスタをスタックに退避
        stwu    r2, -4(r1)
        
        lis     r4, hi16(temp)
        addi    r4, r4, lo16(temp)
        li      r0, 10          ; '\n'
        stb     r0, 0(r4)
        li      r5, 1
        li      r0, 4           ; sys_write
        sc                      ; system call

        lwz     r2, 0(r1)
        mtlr    r2              ; リンクレジスタを復帰
        addi    r1, r1, 4
        
        blr

_exit:
        bl      _print_lf
        li      r3, 0
        li      r0, 1           ; sys_exit
        sc


;; 文字列

        .data
        .align 2

line:
        .asciz  "ゆめよりもはかなき世のなかをなげきわびつゝあかしくらすほどに四月十よひにもなりぬれば木のしたくらがりもてゆく"
        .align  2

temp:
        .asciz  "  "

Index

Feed

Other

Link

Pathtraq

loading...