←練習問題へ :  INDEX :  次の章へ→


7-9.練習問題

問題
4-9で作った1行入力サブルーチンを用いて、文字列2つを入力する。2回目の文字列が1回目の文字列の中に何回出現するかどうかを数えて、その出現回数を表示するプログラムを作れ。

考え方
  1. 1回目の文字列を入力
  2. 何も入力されていなかったらエラーメッセージを表示して終了
  3. 2回目の文字列を入力
  4. 何も入力されていなかったらエラーメッセージを表示して終了
  5. 1回目の文字列の方が2回目の文字列より短かったらエラーメッセージを表示して終了
  6. DS:SIは1回目の文字列の先頭を指す
  7. ES:DIは2回目の文字列の先頭を指す
  8. CMPSBで比較する
  9. 同じであれば個数を1増やす
  10. SIを1増やして、7に戻る。1回目の文字列の最後まできたら終了
  11. 個数を表示して終了

解答

START:
	push	ds
	pop	es
	cld
	mov	bx,offset DAT1
	mov	cx,70
	call	LINEINP
	or	ax,ax		;1st data ==0 -> ERR
	jz	ERR2
	mov	LEN1,ax

	mov	bx,offset DAT2
	call	LINEINP
	or	ax,ax
	jz	ERR2		;2nd data == 0 -> ERR

	mov	LEN2,ax
	cmp	LEN1,ax
	jae	SCAN		;2nd data > 1st data ERR

ERR1:	mov	dx,offset ERRMSG1
	jmp	short ERR_END
ERR2:	mov	dx,offset ERRMSG2
;	jmp	short ERR_END
ERR_END:
	mov	ah,9
	int	21h		;エラーメッセージ表示
	mov	ax,4cffh
	int	21h

SCAN:	mov	si,offset DAT1-1
	mov	ax,LEN1
	add	ax,offset DAT1	;ax<= END address
SCAN2:	inc	si
SCAN3:	cmp	si,ax
	jae	SCAN_END
	mov	di,offset DAT2
	mov	cx,LEN2
	push	si
	repe	cmpsb		;ds:si = DAT1
				;es:di = DAT2
	pop	si
	jnz	SCAN2
	add	si,LEN2
	inc	KOSU
	jmp	short SCAN3
SCAN_END:

	mov	ax,KOSU
	call	DISPN

_END:	call	KAIGYOU
	mov	ax,KOSU
	mov	ah,4ch
	int	21h

;+------------------------
;|1行入力
;|最後には 0Dh が入る
;+------------------------
;|in  bx <= buffer(offset)
;|    cx <= 最大文字数
;+------------------------
;|out ax <= 入力文字数
;|          (改行なし) 
;+------------------------
;|break ; ax
;+------------------------
LINEINP	proc
	push	dx
	push	di
	inc	cx
	mov	di,0
INPUT:	mov	ah,8
	int	21h

	cmp	al,8		;BSか?
	jz	_BS

	mov	[bx+di],al

	cmp	al,0dh		;リターンキーか?
	jz	_RET

	cmp	di,cx		;文字数制限大丈夫?
	jz	OVER
	inc	di

DISPC:	mov	dl,al
	mov	ah,2
	int	21h		;disp char

	jmp	short INPUT

OVER:
	mov	[di+bx-1],al	;入力可能文字数を超えていた場合の処理
	push	ax
	mov	ah,2
	mov	dl,8
	int	21h		;disp BS
	pop	ax
	jmp	short DISPC


_BS:	or	di,di
	jz	INPUT		;何も入力されていなかったらBS無効

	mov	ah,2
	mov	dl,8
	int	21h		;disp BS
	mov	ah,2
	mov	dl,' '
	int	21h		;disp SP
	mov	ah,2
	mov	dl,8		;disp BS
	int	21h
	dec	di
	jmp	short INPUT

_RET:
	mov	ah,2
	mov	dl,0dh
	int	21h
	mov	ah,2
	mov	dl,0ah
	int	21h		;改行

	mov	ax,di
	pop	di
	pop	dx
	dec	cx
	ret

;+--------------
;|数字を表示する
;+--------------
;|IN  cx <= 数字
;+--------------
;|OUT none
;+--------------
;|break none
;+--------------
DISPN	proc
	pusha
	mov	cx,5
DISPN_10:
	xor	dx,dx
	mov	bx,10
	div	bx
	add	dl,30h
	push	dx
	loop	DISPN_10

	mov	cx,5
DISPN_20:
	pop	dx
	mov	ah,6
	int	21h
	loop	DISPN_20
	popa
	ret
;+------------
;|改行する
;+------------
;;break ; none
;+------------
KAIGYOU	proc
	push	ax
	push	dx
	mov	ah,2
	mov	dl,0dh
	int	21h
	mov	dl,0ah
	int	21h
	pop	dx
	pop	ax
	ret

KOSU	dw	0
ERRMSG1	db	'2nd string is longer than 1st one!',0dh,0ah,24h
ERRMSG2	db	'You inputed nothing!',0dh,0ah,24h
DAT1	db	71 dup(0)
DAT2	db	71 dup(0)
LEN1	dw	?
LEN2	dw	?

	end	

←練習問題へ :  INDEX :  次の章へ→