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

5-6. 演習問題

演習5-6

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

  1. レジスタ r16 に 0xA0 を入れる
    
        ldi   r16,0xa0
    
  2. 出力ポート PORTB に 0x55 を出力する
    
        ldi    r16,0x55
        out    PORTB,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,high(RAMEND)
        out     SPH,r16 
	ldi	r16,low(RAMEND)
	out	SPL,r16
	ldi	r16,1<<pb5
	out	ddrb, r16

.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

演習5-8

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


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

.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

演習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
  
  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-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
   
  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-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>
東京電機大学工学部情報通信工学科