例3.36
编写程序,传输20字节的字符串。
DATSEG SEGMENT
DATAX DB 'ABCDEFGHIJKLMNOPQRST'
DATAY DB 20 DUP(?)
DATSEG ENDS
; - - - - - - - - - - - - - - - - - - - -
CODSEG SEGMENT
ASSUME CS:CODSEG,DS:DATSEG,ES:DATSEG
START: MOV AX,DATSEG
MOV DS,AX ; initialize the data segment
MOV ES,AX ; initialize the extra segment
CLD ; clear direction flag for autoincrement
MOV SI,OFFSET DATAX ; load the source pointer
MOV DI,OFFSET DATAY ; load the destination pointer
MOV CX,20 ; load the counter
REP MOVSB ; repeat until CX becomes zero
MOV AX,4C00H ; return to DOS
INT 21H
CODSEG ENDS
END START
串传送指令将SI所指示的数据段中的数据传送到由DI指示的附加段中,本例将源串和目的串都设置在同一个段DATSEG中,因此,DS和ES都定义为DATSEG。
例3.37
编写程序:
(1)用STOS指令将0AAH存入100个存储器字节;
(2)利用LODS指令测试这些存储器单元的内容是否是0AAH,如果不是则显示"bad memory"。
DTSEG SEGMENT
DATAM DB 100 DUP(?)
MESG DB 'bad memory', '$'
DTSEG ENDS
; - - - - - - - - - - - - - - - - - -
CDSEG SEGMENT
ASSUME CS:CDSEG,DS:DTSEG,ES:DTSEG
START: MOV AX,DTSEG ; initialize
MOV DS,AX ; DS register
MOV ES,AX ; and ES register
CLD ; clear DF for increment
MOV CX,50 ; load the counter(50 words)
MOV DI,OFFSET DATAM ; load the pointer for destination
MOV AX,0AAAAH ; load the pattern
REP STOSW ; repeat until CX=0
; bring in the pattern and test it one by one
MOV SI,OFFSET DATAM ; load the pointer for source
MOV CX,100 ; load the counter(100 bytes)
AGAIN: LODSB ; load into AL from DS:SI
XOR AL,0AAH ; is pattern the same?
JNZ OVER ; if not the same, then exit
LOOP AGAIN ; continue until CX=0
JMP EXIT ; exit program
OVER: MOV AH,09 ; display
MOV DX,OFFSET MESG ; the message
INT 21H ; routine
EXIT: MOV AX,4C00H ; return to DOS
INT 21H
CDSEG ENDS
END START
把0AAH存入100个字节是通过执行50次的字操作来完成的。在测试部分,LODSB指令把存储器字节的内容取到AL,并和数据0AAH异或,如果这两个数相同,ZF=1,则继续进行下一个数的测试。如果两数不同,则ZF=0,转去执行显示字符串的BIOS功能调用。显示字符串用了三条指令,首先在AH中装入的显示字符串的功能号09,然后在DX中装入字符串的地址,再用INT
21H调用BIOS例程,完成显示指定字符串的功能。
例3.38
假设有人将电子字典中的"LABEL"误拼为"LABLE",编写程序比较这两个词,并根据比较结果显示
(1)如果相同,则显示"The spelling is correct";
(2)如果不同,则显示"Wrong splling"。
DATASEG SEGMENT
DAT_DICT DB 'LABEL'
DAT_TYPE DB 'LABLE'
MESS1 DB 'The spelling is correct ','$'
MESS2 DB 'Wrong spelling ','$'
DATASEG ENDS
; - - - - - - - - - - - - - - - - - - - - -
CODESEG SEGMENT
ASSUME CS:CODESEG,DS:DATASEG,ES:DATASEG
START: MOV AX,DATASEG
MOV DS,AX ; initialize the data segment
MOV ES,AX ; initialize the extra segment
CLD ; DF=0 for autoincrement
MOV SI,OFFSET DAT_DICT ; SI is source pointer
MOV DI,OFFSET DAT_TYPE ; DI is destination pointer
MOV CX,05 ; load the counter
REPE CMPSB ; repeat as long as equal or until CX=0
JE OVER ; if ZF=1 then display mess1
MOV DX,OFFSET MESS2 ; if ZF=0 then display mess2
JMP DISP
OVER: MOV DX,OFFSET MESS1
DISP: MOV AH,09 ; display message
INT 21H
MOV AX,4C00H ; return to DOS
INT 21H
CODSEG ENDS
END START
用CMPSB指令可将两个串中的字符逐一比较,在比较SI和DI指向的第一对字符时,根据比较结果设置ZF并使(SI)+1,(DI)+1以及(CX)-1。因为第一对字符是相同的('L'),所以ZF=1,于是由REPE控制再重复比较下一对字符。直到比较第四对字符'E'和'L'时,由于它们不相同,ZF设置为0,所以串比较结束。打印的信息应是:'Wrong
spelling '。
例3.39
编写程序,将姓名中的HU DAMING(胡大明)修改为HU DANING(胡大宁),并显示出正确的姓名。
DATA SEGMENT
NAME DB 'HU DAMING', '$'
DATA ENDS
; - - - - - - - - - - - -
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,ES:DATA
START: MOV AX,DATA
MOV DS,AX ; initialize the data segment
MOV ES,AX ; initialize the extra segment
CLD ; DF=0 for autoincrement
MOV AL,'M'
MOV DI,OFFSET NAME ; DI is destination pointer
MOV CX,09 ; load the counter
REPNE SCASB ; repeat as long as equal or until CX=0
JNE DISP ; if ZF=0 then display name
DEC DI ; decrement to point at 'M'
MOV BYTE PTR [DI],'N' ; replace 'M' with 'N'
DISP: MOV AH,09 ; display the corrected name
MOV DX,OFFSET NAME
INT 21H
MOV AX,4C00H ; return to DOS
INT 21H
CODE ENDS
END START
本例中,AL寄存器中的字符'M'与NAME中的每个字符进行比较,如果串中字符与'M'不同,则DI增量,CX减量,继续进行下一个字符的扫描比较,一直到发现'M'或CX=0为止。在本例中,因为发现了'M',比较的结果使ZF=1,同时DI已指向了下一个字符'I',所以DI退回一个字符位置(DEC
DI),并用N取代M。