;+------------------------------------
;|题目:定义一个字符串X和一个字节型变量COUNT,找出X中’A’的个数,
;| 并存放在COUNT中。
;|来源:http://tieba.baidu.com/p/5983779502
;+------------------------------------
;|编程释义:fasmfan / masm v4.00 编译通过 / 2018.12.20
;+------------------------------------
;编写堆栈段
STACK segment STACK
db 4 dup('MYSTACKS');Debug时,可以看到这些字符位于哪里,方便定位。
STACK ends
;编写数据段
_DATA segment
X db 'ABCDElki A1234 Aeoaqi Aaedl; Ads'
;提示,上面的字符串也是一个数组,一个字符占一个字节,各元素的位置如下:
; 'A' <==> X[0]
; 'B' <==> X[1]
; 'C' <==> X[2] ...... 下面程序中我用X[SI]来定位字符
len equ $-x ;
;len就是一个符号化的数字,又称等价符。它由汇编器在汇编时计算出具体
;数,备用。这里用等价符的好处是:数组中的元素添一个或者删一个,都不
;需要改动其他地方了。len不是变量,不占内存。
count dw 0 ;初值为0
_DATA ends
;编写代码段
_TEXT segment
assume cs:_TEXT,ds:_DATA,ss:STACK
main proc far ;DOS调入它时用far调用
mov ax,_DATA ;取数据段段地址
mov ds,ax ;送ds(这两句是设置数据段寄存器)
;程序从下面正式开始
;配置循环用到的寄存器
xor si,si ;si用作一个位置计数器,为程序查找X数组元素提供参照点
;初值为0,
mov cx,len ;配置循环次数。CX是循环记数器,每次循环自动递减1。
;len是等价符,由汇编器汇编时变换为具体数
;下面做扫描X数组、统计'A'字符的循环
next:
cmp X[si],'A' ;将位于X[SI]地址的数组元素与'A'的编码相比较
jne bottom ;不相等那就跳到bottom标号处。
inc count ;否则就是相等啊,相等就让count加个1。
bottom:
inc si ;调整一下SI,使X[SI]定位下一个元素
loop next ;cx减1,如果cx不等于0,那就进入下一循环
mov bx,count ;为调用disp_decimal提供参数
call disp_decimal;调用子程序,以十进制显示bx中的数
;如果还没学到子程序知识,上面两句可注销。
mov al,0 ;设置退出码(可供DOS的脚本程序捕捉,这句可省)
mov ah,4ch ;设置中断号
int 21h ;返回DOS
main endp ;
;+------------------------------------
;子程序:将16 bit无符号整数转换为十进制数串并输出
;输 入:bx=要转换并输出的数
;输 出:在屏幕上显示bx中的数
;+------------------------------------
disp_decimal proc
push ax ;保护入场时的ax寄存器值
push bx ;保护入场时的bx寄存器值
push cx ;保护入场时的cx寄存器值
push dx ;保护入场时的dx寄存器值
;循环做除法,第一次循环求出个位,第二次循环求出十位...
mov ax,bx ;把bx传过来的数据转给ax,下面dx与ax组合作为被除数
mov bx,10 ;着bx作为除数
xor cx,cx ;着cx作为压栈记数器,初值为0
lab9078:
xor dx,dx ;dx清0,以便配合ax做除法(dx:ax组成一个32位的被除数)
div bx ;做dx:ax / bx。(如果是div bl,那被除数就是ax了)。
push dx ;余数压栈。(除后,余数在DX中,商在ax中)
inc cx ;记数器记下压栈的次数
cmp ax,0 ;商为0吗?(商为0,那说明除法做完了啊)
jnz lab9078 ;不为0就跳转
mov ah,2 ;如果为0就开始做显示工作,这里配置中断号
lab9079: ;循环体的头
pop dx ;弹出压栈的数据给DX,根据题意,只有DL的值有意义
add dl,'0' ;调整为对应数字字符的ASCII编码
int 21h ;调用中断显示之。(AH在上面已经配置好了)
loop lab9079;cx减1,如果cx不等于0,那就进入下一循环
pop dx ;恢复dx的入场值。出栈的顺序不要搞错,后进的先出。
pop cx ;恢复cx的入场值
pop bx ;恢复bx的入场值
pop ax ;恢复ax的入场值
ret ;返回调用程序
disp_decimal endp ;
_TEXT ends ;
end main ;告诉汇编器,汇编到此结束,运行时的入口地址是main。
;|题目:定义一个字符串X和一个字节型变量COUNT,找出X中’A’的个数,
;| 并存放在COUNT中。
;|来源:http://tieba.baidu.com/p/5983779502
;+------------------------------------
;|编程释义:fasmfan / masm v4.00 编译通过 / 2018.12.20
;+------------------------------------
;编写堆栈段
STACK segment STACK
db 4 dup('MYSTACKS');Debug时,可以看到这些字符位于哪里,方便定位。
STACK ends
;编写数据段
_DATA segment
X db 'ABCDElki A1234 Aeoaqi Aaedl; Ads'
;提示,上面的字符串也是一个数组,一个字符占一个字节,各元素的位置如下:
; 'A' <==> X[0]
; 'B' <==> X[1]
; 'C' <==> X[2] ...... 下面程序中我用X[SI]来定位字符
len equ $-x ;
;len就是一个符号化的数字,又称等价符。它由汇编器在汇编时计算出具体
;数,备用。这里用等价符的好处是:数组中的元素添一个或者删一个,都不
;需要改动其他地方了。len不是变量,不占内存。
count dw 0 ;初值为0
_DATA ends
;编写代码段
_TEXT segment
assume cs:_TEXT,ds:_DATA,ss:STACK
main proc far ;DOS调入它时用far调用
mov ax,_DATA ;取数据段段地址
mov ds,ax ;送ds(这两句是设置数据段寄存器)
;程序从下面正式开始
;配置循环用到的寄存器
xor si,si ;si用作一个位置计数器,为程序查找X数组元素提供参照点
;初值为0,
mov cx,len ;配置循环次数。CX是循环记数器,每次循环自动递减1。
;len是等价符,由汇编器汇编时变换为具体数
;下面做扫描X数组、统计'A'字符的循环
next:
cmp X[si],'A' ;将位于X[SI]地址的数组元素与'A'的编码相比较
jne bottom ;不相等那就跳到bottom标号处。
inc count ;否则就是相等啊,相等就让count加个1。
bottom:
inc si ;调整一下SI,使X[SI]定位下一个元素
loop next ;cx减1,如果cx不等于0,那就进入下一循环
mov bx,count ;为调用disp_decimal提供参数
call disp_decimal;调用子程序,以十进制显示bx中的数
;如果还没学到子程序知识,上面两句可注销。
mov al,0 ;设置退出码(可供DOS的脚本程序捕捉,这句可省)
mov ah,4ch ;设置中断号
int 21h ;返回DOS
main endp ;
;+------------------------------------
;子程序:将16 bit无符号整数转换为十进制数串并输出
;输 入:bx=要转换并输出的数
;输 出:在屏幕上显示bx中的数
;+------------------------------------
disp_decimal proc
push ax ;保护入场时的ax寄存器值
push bx ;保护入场时的bx寄存器值
push cx ;保护入场时的cx寄存器值
push dx ;保护入场时的dx寄存器值
;循环做除法,第一次循环求出个位,第二次循环求出十位...
mov ax,bx ;把bx传过来的数据转给ax,下面dx与ax组合作为被除数
mov bx,10 ;着bx作为除数
xor cx,cx ;着cx作为压栈记数器,初值为0
lab9078:
xor dx,dx ;dx清0,以便配合ax做除法(dx:ax组成一个32位的被除数)
div bx ;做dx:ax / bx。(如果是div bl,那被除数就是ax了)。
push dx ;余数压栈。(除后,余数在DX中,商在ax中)
inc cx ;记数器记下压栈的次数
cmp ax,0 ;商为0吗?(商为0,那说明除法做完了啊)
jnz lab9078 ;不为0就跳转
mov ah,2 ;如果为0就开始做显示工作,这里配置中断号
lab9079: ;循环体的头
pop dx ;弹出压栈的数据给DX,根据题意,只有DL的值有意义
add dl,'0' ;调整为对应数字字符的ASCII编码
int 21h ;调用中断显示之。(AH在上面已经配置好了)
loop lab9079;cx减1,如果cx不等于0,那就进入下一循环
pop dx ;恢复dx的入场值。出栈的顺序不要搞错,后进的先出。
pop cx ;恢复cx的入场值
pop bx ;恢复bx的入场值
pop ax ;恢复ax的入场值
ret ;返回调用程序
disp_decimal endp ;
_TEXT ends ;
end main ;告诉汇编器,汇编到此结束,运行时的入口地址是main。