【汇编学习笔记】3:查询子串出现的位置

来源:互联网 发布:java web嵌入式 编辑:程序博客网 时间:2024/06/05 08:17

已经写了一些汇编程序了,不再过多赘述程序执行流程,这次实验的几个要点如下:
[1]用21H号中断的09H号功能可以输出一个字符串,注意在其结尾需要加上$串结束符。
[2]用21H号中断的0AH号功能可以读入一个字符串,但应在其第一个字节位存下要读的串的最大长度,并留空第二个字节,用于在读入后记录实际读了多长,这个很实用。
[3]寻址用的寄存器不能随便选,一般用BX/SI/DI等(段寄存器默认DS),也可以使用BP(段寄存器默认SS)。
[4]在实模式下访问其它段中的数据,正确的格式是

段跨越前缀:段内位移量标号[地址偏移量]

这是一种抽象简化的形式,实际上:
①段跨越前缀可以不写,而用默认的段寄存器。
②段内位移量标号也可以没有,而用立即寻址/寄存器寻址/直接寻址/寄存器间接寻址/基址变址寻址等。
③地址偏移量可以是很多东西的加和,如基址寄存器/变址寄存器/明确的数等。

但是因为总可以抽象成这样的形式,我认为目前还没有必要去区分使用基址寄存器和变址寄存器,而可以总是把它们扔进[地址偏移量]里面去。

DATAS SEGMENT    HH DB 0AH,0DH,'$'          ;换行回车,注意串结束符    S_T DB 'Enter keyword:','$'    ;查询串(小串)提示    S_Tget DB 30                ;表示最多存30个字符           DB ?                 ;预留!保存实际存的字符数           DB 30 DUP (?)        ;接收S_T提示的输入串    S_M DB 'Enter Sentence:','$';被查询串(大串)提示    S_Mget DB 30                ;表示最多存30个字符           DB ?                 ;预留!保存实际存的字符数           DB 30 DUP (?)        ;接收S_T提示的输入串    S_N DB 'No match.','$'     ;No match.    S_F1 DB 'Match at location:','$'    S_F2 DB 'H of the sentence.','$'DATAS ENDSCODES SEGMENT    ASSUME CS:CODES,DS:DATASSTART:    MOV AX,DATAS    MOV DS,AX    ;主循环    MYXUN:        ;输出小串提示        LEA DX,S_T  ;将S_T的地址给DX        MOV AH,09H  ;9号功能显示DS:DX=串地址的字符串        INT 21H        ;接收字符串        LEA DX,S_Tget        MOV AH,0AH  ;0A号功能接受输入到缓冲区        ;DS:DX=缓冲区首地址        ;(DS:DX)保存缓冲区最大字符数        ;(DS:DX+1)保存实际输入字符数        INT 21H        ;换行回车        LEA DX,HH        MOV AH,09H        INT 21H        ;输出大串提示        LEA DX,S_M  ;将S_T的地址给DX        MOV AH,09H  ;9号功能显示DS:DX=串地址的字符串        INT 21H        ;接收字符串        LEA DX,S_Mget        MOV AH,0AH  ;0A号功能接受输入到缓冲区        ;DS:DX=缓冲区首地址        ;(DS:DX)保存缓冲区最大字符数        ;(DS:DX+1)保存实际输入字符数        INT 21H        ;换行回车        LEA DX,HH        MOV AH,09H        INT 21H        ;剪枝:如果小串比大串长,直接输出'No match.'        MOV AL,DS:S_Mget[1]        CMP DS:S_Tget[1],AL        JA NOMA        ;跳入比较代码块        JMP BJYX    JMP MYXUN   ;跳回(仅作保护措施)    ;带返回码终止(仅作保护措施)    ENDPRO:        MOV AH,4CH        INT 21H    ;找不到    NOMA:        ;输出'No match.'        LEA DX,S_N        MOV AH,09H        INT 21H        ;换行回车        LEA DX,HH        MOV AH,09H        INT 21H    JMP MYXUN   ;跳回主循环    ;找得到    FINDED:        ADD CL,1    ;外循环计数+1就是找到的位置        ;拼成16位被除数        MOV AL,CL        MOV AH,0        ;8位除数        MOV DL,16D        DIV DL        ;除法后,商在AL中,余数在AH中        ;备份一下余数(后面只用备份的值)        MOV CH,AH        ;备份一下商(后面只用备份的值)        MOV CL,AL        ;输出前一半        LEA DX,S_F1        MOV AH,09H        INT 21H        ;调整两个16进制位成字符        MOV AH,2 ;先保证输出状态        ;数字和字母分开处理        CMP CL,10        JB NUM1 ;小于10        JMP CHA1 ;大于等于10        NUM1:            ADD CL,'0'            MOV DL,CL            INT 21H            JMP NEXTFIN2        CHA1:            SUB CL,10            ADD CL,'A'            MOV DL,CL            INT 21H        NEXTFIN2:        ;数字和字母分开处理        CMP CH,10        JB NUM2     ;小于10        JMP CHA2    ;大于等于10        NUM2:            ADD CH,'0'            MOV DL,CH            INT 21H            JMP NEXTFIN3        CHA2:            SUB CH,10            ADD CH,'A'            MOV DL,CH            INT 21H        ;输出后一半,'H'也在里面        NEXTFIN3:            LEA DX,S_F2            MOV AH,09H            INT 21H            ;换行回车            LEA DX,HH            MOV AH,09H            INT 21H    JMP MYXUN ;回到主循环    ;比较一下两个串    BJYX:        MOV AL,0 ;内循环计数初始化        ;外循环总数=两串差值+1        MOV AH,DS:S_Mget[1]        SUB AH,DS:S_Tget[1]        ADD AH,1        ;-----------测试块        ;MOV DL,DS:S_Mget[1]        ;ADD DL,'0'        ;MOV AH,2        ;INT 21H        ;-----------测试块结束        ;外循环计数初始化        MOV CL,0    JMP NEIXUN    ;内循环    NEIXUN:        ;比较DS:S_Tget[(AL)+2]和DS:S_Mget[(CL)+(AL)+2]         ;2是指跨越非内容部分,以下是其实现        MOV BH,0        MOV BL,AL        MOV DL,DS:S_Tget[BX+2]        ADD BL,CL        CMP DL,DS:S_Mget[BX+2]        JNE NEXTWAI ;出现不等时跳到下一层外循环再找        ADD AL,1    ;内循环计数加1        CMP AL,DS:S_Tget[1] ;内循环总次数不超过小串长度        JE FINDED   ;内循环越界结束说明找到    JMP NEIXUN      ;两者都不满足,继续内循环    ;下一层外循环的初始工作    NEXTWAI:        ADD CL,1    ;外循环计数加1        CMP CL,AH   ;比较外循环是否越界结束        JE NOMA ;外循环越界结束说明没找到        MOV AL,0    ;否则将内循环计数清0    JMP NEIXUN      ;然后继续内循环CODES ENDS    END START

这里写图片描述

原创粉丝点击