第10章 应用程序的设计
在前面各章节中,我们侧重介绍了汇编语言程序设计中各组成部分的作用,本章的重点是对前面所学知识的综合运用。希望通过各种不同类型的例子,使读者能够掌握用汇编语言编程的基本技巧。
10.1 字符串的处理程序
字符或字符串是一类重要的非数值计算的处理对象。许多编辑软件都具有字符串查找、替换、大小写的转换、单词的自动识别等功能,网络上的信息搜索也是现在一种常用的功能等,这些功能的实现无疑都要涉及到字符串的处理功能。
为了方便对字符串 的处理,各种常用的编程环境也都给予了足够的支持。如:C语言编程环境提供了大量处理字符串的标准函数,象strlen、strcmp和strcpy等函 数;C 、VC或VB等编程环境提供了字符串类String等。这些函数或类大大方便了程序员的编程。
在计算机系统内,为了加快字符串的处理,在其指令系统中设置了多条处理字符串的指令,其详细内容请参阅第5.2.11节中的介绍。
下面我们将通过几个例子来学习汇编语言处理字符串的方法。
例10.1 编写一个求字符串长度的子程序Strlen,要求字符串的首地址为入口参数,且以ASCII码0为结束符,CX为出口参数,其存放该字符串的长度。
| 解: |
|||
| |
.MODEL SMALL, C |
||
| .DATA |
|||
| buff |
DB "This is a example.", 0 |
||
| .CODE |
|||
| Strlen |
PROC USES AX BX, String:PTR BYTE |
||
| MOV |
BX, String |
||
| XOR |
CX, CX |
||
| MOV |
AL, [BX] |
||
| .WHILE AL!=0 |
|||
| INC |
CX |
||
| INC |
BX |
||
| MOV |
AL, [BX] |
||
| .ENDW |
|||
| RET |
|||
| Strlen |
ENDP |
||
| .STARTUP |
|||
| INVOKE Strlen, ADDR buff |
|||
| .EXIT 0 |
|||
| END |
|||
例10.2 编写一个把字符串中的所有小写字符转换成大写字符的子程序Strupr,要求字符串的首地址和结束符为其入口参数。
| 解: |
|||
| |
.MODEL SMALL, C |
||
| .DATA |
|||
| buff |
DB "This is a example.", 0 |
||
| .CODE |
|||
| Strupr |
PROC USES AX BX, String:PTR BYTE, Tail:BYTE |
||
| MOV |
BX, String |
||
| .REPEAT |
|||
| MOV |
AL, [BX] |
||
| .IF AL>='a' && AL<='z' |
|||
| SUB |
AL, 20H |
||
| MOV |
[BX], AL |
||
| .ENDIF |
|||
| INC |
BX |
||
| .UNTIL |
AL==Tail |
||
| RET |
|||
| Strupr |
ENDP |
||
| .STARTUP |
|||
| INVOKE Strupr, ADDR buff, 0 |
|||
| .EXIT 0 |
|||
| END |
|||
例10.3 编写一个从字符串中拷贝子串的子程序Strncpy,它有四个参数str1、str2、idx和num,其具体功能为把字符串str2中从第idx个(从 0开始记数)字符开始、num个字符传送给str1,字符串str1和str2都是以ASCII码0为结束符。
| 解: |
||||
| |
.MODEL |
SMALL, C |
||
| .DATA |
||||
| str1 |
DB "12345ABCDEF", 0 |
|||
| str2 |
DB 20 DUP('A') |
|||
| .CODE |
||||
| Strlen |
PROC USES AX BX, String:PTR BYTE |
|||
| …… |
;参见例10.1 |
|||
| Strlen |
ENDP |
|||
| Strncpy |
PROC USES AX CX DI SI DS ES, str1:FAR PTR BYTE, str2:FAR PTR BYTE, idx:WORD, num:WORD |
|||
| LES |
DI, str1 |
|||
| LDS |
SI, str2 |
;取两个字符串的首地址 |
||
| INVOKE |
Strlen, SI |
;计算源字符串的长度,在CX中 |
||
| MOV |
AX, idx |
|||
| .IF AX >= CX |
;若字符起点就超过源串的长度 |
|||
| MOV |
BYTE PTR ES:[DI], 0 |
;拷贝的字符串为“空” |
||
| JMP |
over |
|||
| .ENDIF |
||||
| ADD |
SI, AX |
;定源串中字符的起点SI |
||
| MOV |
CX, num |
|||
| CLD |
||||
| .REPEAT |
||||
| LODSB |
||||
| STOSB |
||||
| .UNTILCXZ AL==0 |
||||
| .IF AL!=0 |
;设置目标串的结束符 |
|||
| MOV |
BYTE PTR[DI], 0 |
|||
| .ENDIF |
||||
| over: |
RET |
|||
| Strncpy |
ENDP |
|||
| .STARTUP |
||||
| INVOKE |
Strncpy, ADDR str2, ADDR str1, 3, 5 |
|||
| .EXIT |
0 |
|||
| END |
||||
例10.4 编写一个把字符串中空格和TAB压缩掉的子程序Compress,字符串String是以ASCII码0为结束符。
| 解: |
|||||
| |
.MODEL |
SMALL, C |
|||
| .DATA |
|||||
| SPACE |
EQU 20H |
||||
| TAB |
EQU 9H |
||||
| Buff |
DB "12 3 4 Ab cdef", 0 |
||||
| .CODE |
|||||
| Compress |
PROC USES AX BX SI DS, String:FAR PTR BYTE |
||||
| LDS |
SI, String |
;SI用于扫描字符串的指针 |
|||
| MOV |
BX, SI |
;BX用于存放结果的指针 |
|||
| .REPEAT |
|||||
| MOV |
AL, [SI] |
||||
| INC |
SI |
||||
| .IF AL!=SPACE && AL!=TAB |
|||||
| |
MOV |
[BX], AL |
|||
| INC |
BX |
|
|||
| .ENDIF |
|||||
| .UNTIL AL==0 |
|||||
| RET |
|||||
| Compress |
ENDP |
||||
| .STARTUP |
|||||
| INVOKE Compress, ADDR Buff |
|||||
| .EXIT |
0 |
||||
| END |
|||||
从上面四个例子,我们不难看出处理字符串的一般方法,感兴趣的读者可自行编写实现字符串变小写、整体拷贝、逆转和查找等功能的子程序,甚至还可以建立起自己的字符串处理库文件。


