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
    ;; Mac OS X (PowerPC 32bit)
    ;; % as -o pyramid.o pyramid.s && gcc pyramid.o -o pyramid
    .machine    ppc
    .globl      _main

_main:
    li      r6, 8               ; 高さ n
    li      r7, 0               ; 出力中の行数 i (0-)

_print_line:
    ;; 空白の数 = n-i-1
    sub     r8, r6, r7
    subi    r8, r8, 1
    cmpli   cr7, r8, 0
    bgtl    cr7, _print_spaces  ; サブルーチン

    ;; 星の数 = 辺の長さ - 空白の数 * 2
    ;;     = 2n-1 - 2(n-i-1) = 2i+1
    mulli   r8, r7, 2
    addi    r8, r8, 1
    cmpli   cr7, r8, 0
    bgtl    cr7, _print_stars   ; サブルーチン

    ;; 改行の出力
    li      r4, hi16(lf)
    addi    r4, r4, lo16(lf)
    bl      _print_char         ; サブルーチン

    ;; 繰り返し
    addi    r7, r7, 1
    cmpl    cr7, r6, r7
    bne     cr7, _print_line
    
    ;; sys_exit()
    li      r3, 0
    li      r0, 1
    sc

_print_spaces:
    ;; 出力する文字列(スペース)の準備
    li      r4, hi16(space)
    addi    r4, r4, lo16(space)

    ;; リンクレジスタをスタックに退避
    mflr    r9              ; リンクレジスタを r9 にコピー
    stwu    r9, -4(r1)
    bl     _print_char      ; サブルーチン
    lwzu    r9, 0(r1)
    mtlr    r9              ; r9 をリンクレジスタにコピー
    addi    r1, r1, 4

    subi    r8, r8, 1
    cmpli   cr7, r8, 0
    bgt     cr7, _print_spaces

    ;; サブルーチンから戻る
    blr

_print_stars:
    ;; 出力する文字列(アスタリスク)の準備
    li      r4, hi16(star)
    addi    r4, r4, lo16(star)

    ;; リンクレジスタをスタックに退避
    mflr    r9              ; リンクレジスタを r9 にコピー
    stwu    r9, -4(r1)
    bl      _print_char     ; サブルーチン
    lwzu    r9, 0(r1)
    mtlr    r9              ; r9 をリンクレジスタにコピー
    addi    r1, r1, 4

    subi    r8, r8, 1
    cmpli   cr7, r8, 0
    bgt cr7, _print_stars

    ;; サブルーチンから戻る
    blr

;; 一文字を出力する
;; r4 に文字列のアドレスをセットしておく
_print_char:
    ;; スタックに退避
    subi    r1, r1, 4
    stw     r6, 0(r1)
    subi    r1, r1, 4
    stw     r7, 0(r1)
    subi    r1, r1, 4
    stw     r8, 0(r1)

    ;; sys_write()
    li      r3, 1           ; 標準出力
    li      r5, 1           ; 出力する文字列の長さ
    li      r0, 4           ; sys_write
    sc                      ; 呼び出し

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

    ;; サブルーチンから戻る
    blr

    
    .data
    .align 2

space:
    .asciz      " "

star:
    .asciz      "*"

lf:
    .asciz      "\n"