第 5 回 アセンブラ言語演習解答

5-6. 演習問題

演習5-6

次の操作をする命令の組を書きなさい

  1. レジスタ r16 に 0xA0 を入れる
    
            ldi   r16,0xa0
    
  2. 出力ポート PORTB5 を HIGH にする
    
            sbi     portb,pb5
    
    
            sbi     portb,pb5
    
    
            lds     r16,PORTB_OUT
            ori     r16,1<<5
            sts     PORTB_OUT,r16
    
  3. r16 の値が 0x32 かどうか調べ、等しければ label0 に飛び、等しくなけ れば label1 に飛ぶ
    
            cpi    r16,0x32
            breq   label0
            rjmp   label1
    
  4. r16 の値が 0x45 と比較し、大きければ label0 に飛び、それ以下なら label1 に飛ぶ
    
            cpi    r16,0x45
            breq   label1
            brcc   label0
            rjmp   label1
    
  5. call sub0 を 100回呼ぶ
    
            ldi    r16,100
    loop:   push   r16
            rcall  sub0
            pop    r16
            dec    r16
            brne   loop
    

演習5-7

flashuno.asm のプログラムを改造して、点滅の速さが2倍になるようにしよ う


.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,low(RAMEND)
        out     SPL,r16
        ldi     r16,high(RAMEND)
        out     SPH,r16 
        sbi     ddrb,pb5

.equ    time = 5
main:
        sbi     portb,pb5
        rcall   wait
        cbi     portb,pb5
        rcall   wait
        rjmp    main

.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
wait:
        ldi     wreg0,time
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret
.exit

.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,low(RAMEND)
        out     SPL,r16
        ldi     r16,high(RAMEND)
        out     SPH,r16 
        sbi     ddrc,pc7

.equ    time = 5
main:
        sbi     portc,pc7
        rcall   wait
        cbi     portc,pc7
        rcall   wait
        rjmp    main

.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
wait:
        ldi     wreg0,time
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret
.exit

.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,low(RAMEND)
        out     CPU_SPL,r16
        ldi     r16,high(RAMEND)
        out     CPU_SPH,r16 
        lds     r16,PORTE_DIR
        ori     r16,1<<2
        sts     PORTE_DIR,r16
.equ    time = 5
main:
        lds     r17,PORTE_OUT
        ori     r17,1<<2
        sts     PORTE_OUT,r17
        rcall   wait
        lds     r17,PORTE_OUT
        andi    r17,~(1<<2)
        sts     PORTE_OUT,r17
        rcall   wait
        rjmp    main

.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
wait:
        ldi     wreg0,time
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret
.exit

演習5-8

flashuno.asm のプログラムを改造して、点滅の速さが1/2倍になるようにしよ う


.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,low(RAMEND)
        out     SPL,r16
        ldi     r16,high(RAMEND)
        out     SPH,r16 
        sbi     ddrb,pb5

.equ    time = 20
main:
        sbi     portb,pb5
        rcall   wait
        cbi     portb,pb5
        rcall   wait
        rjmp    main

.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
wait:
        ldi     wreg0,time
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret
.exit

.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,low(RAMEND)
        out     SPL,r16
        ldi     r16,high(RAMEND)
        out     SPH,r16 
        sbi     ddrc,pc7

.equ    time = 20
main:
        sbi     portc,pc7
        rcall   wait
        cbi     portc,pc7
        rcall   wait
        rjmp    main

.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
wait:
        ldi     wreg0,time
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret
.exit

.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,low(RAMEND)
        out     CPU_SPL,r16
        ldi     r16,high(RAMEND)
        out     CPU_SPH,r16 
        lds     r16,PORTE_DIR
        ori     r16,1<<2
        sts     PORTE_DIR,r16
.equ    time = 20
main:
        lds     r17,PORTE_OUT
        ori     r17,1<<2
        sts     PORTE_OUT,r17
        rcall   wait
        lds     r17,PORTE_OUT
        andi    r17,~(1<<2)
        sts     PORTE_OUT,r17
        rcall   wait
        rjmp    main

.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
wait:
        ldi     wreg0,time
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret
.exit

演習5-9

r16に入れた数だけ、0.1秒ずつLEDを点滅した後、1秒消灯する nblink というサブルーチンを作りなさい。 さらに、 次のプログラムと結合して正常に動作することを確かめなさい。


.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,high(RAMEND)
        out     SPH,r16 
        ldi     r16,low(RAMEND)
        out     SPL,r16
        sbi     ddrb,pb5
main:
        ldi     r16,0
loop:
        inc     r16
        push    r16
        rcall   nblink
        pop     r16
        cpi     r16,4
        brne    loop
        rjmp    main

.equ        shorttime = 4
.equ        longtime = 40
.def        wreg0 = r20
.def        wreg1 = r21
.def        wreg2 = r22
shortwait:
        ldi     wreg0,shorttime
        rjmp    wait0
longwait:
        ldi     wreg0,longtime
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret

nblink:
        sbi     portb,pb5
        rcall   shortwait
        cbi     portb,pb5
        rcall   shortwait
        dec     r16
        brne    nblink
        rcall   longwait
        ret
.exit

.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,high(RAMEND)
        out     SPH,r16 
        ldi     r16,low(RAMEND)
        out     SPL,r16
        sbi     ddrc,pc7
main:
        ldi     r16,0
loop:
        inc     r16
        push    r16
        rcall   nblink
        pop     r16
        cpi     r16,4
        brne    loop
        rjmp    main

.equ        shorttime = 4
.equ        longtime = 40
.def        wreg0 = r20
.def        wreg1 = r21
.def        wreg2 = r22
shortwait:
        ldi     wreg0,shorttime
        rjmp    wait0
longwait:
        ldi     wreg0,longtime
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret

nblink:
        sbi     portc,pc7
        rcall   shortwait
        dec     r16
        cbi     portc,pc7
        rcall   shortwait
        dec     r16
        brne    nblink
        rcall   longwait
        ret
.exit

.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi    r16,low(RAMEND)
        out    CPU_SPL,r16
        ldi    r16,high(RAMEND)
        out    CPU_SPH,r16 
        lds    r16,PORTE_DIR
        ori    r16,1<<2
        sts    PORTE_DIR,r16

main:
        ldi    r16,0
loop:
        inc    r16
        push   r16
        rcall  nblink
        pop    r16
        cpi    r16,4
        brne   loop
        rjmp   main

.equ    shorttime = 1
.equ    longtime = 10
.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
shortwait:
        ldi    wreg0,shorttime
        rjmp   wait0
longwait:
        ldi    wreg0,longtime
wait0:
        ldi    wreg1,0
wait1:
        ldi    wreg2,0
wait2:
        nop
        dec    wreg2
        brne   wait2
        dec    wreg1
        brne   wait1
        dec    wreg0
        brne   wait0
        ret

nblink:
        lds    r17,PORTE_OUT
        ori    r17,1<<2
        sts    PORTE_OUT,r17
        rcall  shortwait
        lds    r17,PORTE_OUT
        andi   r17,~(1<<2)
        sts    PORTE_OUT,r17
        rcall  shortwait
        dec    r16
        brne   nblink
        rcall  longwait
        ret
.exit

演習5-10

番兵が0の数列をdbで確保し、各数列の値でblink()メソッドを呼ぶプログラム を 書きなさい。


.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,high(RAMEND)
        out     SPH,r16 
        ldi     r16,low(RAMEND)
        out     SPL,r16
        sbi     ddrb,pb5
main:
        ldi     ZH,high(sampleadr)
        ldi     ZL,low(sampleadr)
loop:
        lpm     r16,Z+
        cpi     r16,0
        breq    main
        rcall   nblink
        rjmp    loop
      
sample:
.db     3,3,7,0
.equ    sampleadr = sample<<1
   
.equ    shorttime = 4
.equ    longtime = 40
.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
shortwait:
        ldi     wreg0,shorttime
        rjmp    wait0
longwait:
        ldi     wreg0,longtime
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret
nblink:
        sbi     portb,pb5
        rcall   shortwait
        cbi     portb,pb5
        rcall   shortwait
        dec     r16
        brne    nblink
        rcall   longwait 
        ret
.exit

.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,high(RAMEND)
        out     SPH,r16 
        ldi     r16,low(RAMEND)
        out     SPL,r16
        sbi     ddrc,pc7
main:
        ldi     ZH,high(sampleadr)
        ldi     ZL,low(sampleadr)
loop:
        lpm     r16,Z+
        cpi     r16,0
        breq    main
        rcall   nblink
        rjmp    loop
      
sample:
.db     3,3,7,0
.equ    sampleadr = sample<<1
   
.equ    shorttime = 4
.equ    longtime = 40
.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
shortwait:
        ldi     wreg0,shorttime
        rjmp    wait0
longwait:
        ldi     wreg0,longtime
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret
nblink:
        sbi     portc,pc7
        rcall   shortwait
        cbi     portc,pc7
        rcall   shortwait
        dec     r16
        brne    nblink
        rcall   longwait 
        ret
.exit

.cseg
.org    0x0000
        rjmp    reset
.org    INT_VECTORS_SIZE
reset:
        ldi     r16,low(RAMEND)
        out     CPU_SPL,r16
        ldi     r16,high(RAMEND)
        out     CPU_SPH,r16 
        lds     r16,PORTE_DIR
        ori     r16,1<<2
        sts     PORTE_DIR,r16
main:
        ldi    ZH,high(sampleadr)
        ldi    ZL,low(sampleadr)
loop:
        lpm    r16,Z+
        cpi    r16,0
        breq   main
        rcall  nblink
        rjmp   loop
        
sample:
.db     3,3,7,0
.equ    sampleadr = sample<<1

.equ    shorttime = 1
.equ    longtime = 10
.def    wreg0 = r20
.def    wreg1 = r21
.def    wreg2 = r22
shortwait:
        ldi     wreg0,shorttime
        rjmp    wait0
longwait:
        ldi     wreg0,longtime
wait0:
        ldi     wreg1,0
wait1:
        ldi     wreg2,0
wait2:
        nop
        dec     wreg2
        brne    wait2
        dec     wreg1
        brne    wait1
        dec     wreg0
        brne    wait0
        ret

nblink:
        lds     r17,PORTE_OUT
        ori     r17,1<<2
        sts     PORTE_OUT,r17
        rcall   shortwait
        lds     r17,PORTE_OUT
        andi    r17,~(1<<2)
        sts     PORTE_OUT,r17
        rcall   shortwait
        dec     r16
        brne    nblink
        rcall   longwait
        ret
.exit

演習5-11

4番とGNDをつないだときだけ、LED が点灯するプログラムを作りなさい。


  .cseg
  .org        0x0000
      rjmp        reset
  .org        INT_VECTORS_SIZE
reset:
  ldi     r16,high(RAMEND)
  out     SPH,r16 
  ldi                r16,low(RAMEND)
  out                SPL,r16
  
  sbi                ddrb,pb5
  cbi                ddrd,pd4
  sbi                portd,pd4
main:
  sbic        pind,pd4
  rjmp        off
  sbi                portb,pb5
  rjmp        main
off:        
  cbi                portb,pb5
  rjmp        main
  .exit

演習5-12

4番とGNDをつないだときは、1秒おきに2回LEDが点滅、つないでない時は 1秒おきに短くLEDが点滅するプログラムを作りなさい。


    ;
; ex512.asm
;
; Created: 2022/10/13 15:57:57
; Author : sakamoto
;


    .cseg
    .org        0x0000
    rjmp        reset
    .org        INT_VECTORS_SIZE
reset:
    ldi     r16,high(RAMEND)
    out     SPH,r16 
    ldi     r16,low(RAMEND)
    out                SPL,r16
    
    sbi                ddrb,pb5
    cbi                ddrd,pd4
    sbi                portd,pd4
main:
    sbic                pind,pd4
    rjmp                off
    ldi        r16,2
    rcall                nblink
    rjmp                main
off:
    ldi        r16,1
    rcall        nblink
    rjmp        main

  
nblink:
    sbi                portb,pb5
    rcall        shortwait
    cbi                portb,pb5
    rcall        shortwait
    dec                r16
    brne        nblink
    rcall        longwait
    ret

    .equ        shorttime = 4
    .equ        longtime = 40
    .def        wreg0 = r20
    .def        wreg1 = r21
    .def        wreg2 = r22
shortwait:
    ldi                wreg0,shorttime
    rjmp        wait0
longwait:
    ldi                wreg0,longtime
wait0:
    ldi                wreg1,0
wait1:
    ldi                wreg2,0
wait2:
    nop
    dec                wreg2
    brne        wait2
    dec                wreg1
    brne        wait1
    dec                wreg0
    brne        wait0
    ret
    .exit

演習5-13

4番とGNDをつないだときは、1秒おきにLEDが1回点滅、2回点滅、3回点滅、 1回点滅,2回点滅、3回点滅と繰り返すが、 つないでない時は同じ回数の点滅を繰り返すプログラムを作りなさい。 つまり、3回点滅の時に線を外せば、そのまま3回点滅を繰り返し、 1回点滅の時に線を外すと1回点滅を繰り返すようにしなさい。


    ;
    ; ex513.asm
    ;
    ; Created: 2022/10/13 16:04:01
    ; Author : sakamoto
    ;
    
     .cseg
      .org        0x0000
          rjmp        reset
      .org        INT_VECTORS_SIZE
    reset:
          ldi     r16,high(RAMEND)
          out     SPH,r16 
          ldi                r16,low(RAMEND)
          out                SPL,r16
        
          sbi                ddrb,pb5
          cbi                ddrd,pd4
          sbi                portd,pd4
    
          .def        counter = r16
    main:
            ldi                counter,1
    loop:
          push        counter
          rcall                nblink
          pop        counter
          sbis                pind,pd4
          inc        counter
          cpi        counter,4
          brne        loop
          rjmp                main
      
    nblink:
          sbi                portb,pb5
          rcall        shortwait
          cbi                portb,pb5
          rcall        shortwait
          dec                counter
          brne        nblink
          rcall        longwait
          ret
    
          .equ        shorttime = 4
          .equ        longtime = 40
      .def        wreg0 = r20
      .def        wreg1 = r21
      .def        wreg2 = r22
      shortwait:
          ldi                wreg0,shorttime
          rjmp        wait0
      longwait:
          ldi                wreg0,longtime
      wait0:
          ldi                wreg1,0
      wait1:
          ldi                wreg2,0
      wait2:
          nop
          dec                wreg2
          brne        wait2
          dec                wreg1
          brne        wait1
          dec                wreg0
          brne        wait0
          ret
      .exit

坂本直志 <sakamoto@c.dendai.ac.jp>
東京電機大学工学部情報通信工学科