DATA SEGMENT //定义段DATA
STR DB “abcdef123456”,-1 //符号地址STR内存放单字节数据
//(共占用13 个单元):“abcdef123456”,-1
LEN DW ? //为符号地址LEN保留一个字的空间
//(即保留两个字节)
DATA ENDS //DATA段结束
STAK SEGMENT //定义段STAK
DB 128 DUP(?) //为堆栈段保留128个字节
STAK ENDS //STAK段结束
CODE SEGMENT //定义段CODE
ASSUME CS: CODE, DS: DATA, SS:STAK //规定CODE为代码段;
//DATA为数据段;STAK为堆栈段
START: //开始标记
MOV AX, DATA //将数据段首址存入AX寄存器
MOV DS, AX //将AX寄存器的值存入数据段奇存器DS(与上面行
//一起,实现为DS段寄存器赋初值,使DS指向数据
//数首地址,也就是符号STR代表的地址,里面存
//放着“a”)
MOV AX, STAK //与下面一行结合,为堆栈段寄存器SS赋初值,功
//能类似于上面两行
MOV SS, AX
LEA SI, STR //将STR的地址赋给源指针SI(即存放“a”的地址)
CALL SCONT //调用子程序scont
MOV LEN, BX //子程序结束后将计数器BX的值存入符号地址LEN
MOV AH, 4CH //将16进制数4C存入AH,AH里的数用于指明DOS调用
//的功能号
INT 21H //DOS系统功能调用(功能号由上一句中AH指明:4CH,即
//终止当前程序并返回调用程序)
SCONT PROC NEAR //定义段内调用子程序SCONT
PUSH SI //将源指针SI的当前值入栈保存
XOR BX, BX //将BX清零
MOV SI, BX //将BX值作为地址偏移量赋给SI
NEXT: //标记NEXT
CMP BYTE PTR[SI],-1 //字节比较:源数据地址:PTR的地址加上SI的值,
//用这个地址里面的数据同-1相比较(例如,最开始
//时,是a同-1比较)
JZ OVER //如果相等则跳转到标记OVER
INC BX //BX增1,BX用于计数
INC SI //SI增1,SI用于增加偏移值
JMP NEXT //跳转到标记NEXT
OVER: //标记OVER
POP SI //从堆栈区恢复SI
RET //返回调用处
SCONT ENDP //子程序SCONT结束
CODE ENDS //代码段结束
END START //程序结束
1、 请试着改变字符串“abcdef123456”(注意不要改变该字符串后的-1),结合存储器中数据段LEN值的变化,分析此程序主要功能是什么?
答:此程序的主要功能是统计字符串中字符的个数,其值最终保存在符号地址LEN。
2、 本程序中的一个子程序是用来实现什么功能的?请画出调用此子程序前后堆栈段的数据变化情况。(请注意此子程序是段内调用!)
答:子程序中,将字符串中各字符依次同数字-1相比较,以此判断字符串是否已经结束,如果没结束,则将BX记数器增1,并继续用下一个字符比较,直至源数据为-1为止。
由于此处不便画图,所以后一问仅作说明:调用子程序时,系统会自动将IP地址入栈(段内调用时CS不入栈),注意:高位先入,低位后入,子程序运行时,又将SI的值入了栈,子程序将要结束时,先取出SI,执行RET时,系统又会自动将IP出栈。
3、请试着将该程序中的子程序调用改成段间调用。并画出段间调用子程序前后的堆栈段的数据变化情况。
要改为段间调用,则需要做以下工作:将SCONT PROC NEAR改为SCONT PROC FAR,将CALL SCONT改为CALL FAR PTR SCONT,并将它们之间的内容剪切下来,作为另一段的内容。(也就是在CODE ENDS后面新建一个段:例如THESUB SEGMENT作开头,THESUB ENDS作结尾,把先前剪下来的内容放在它们之间。)
这样,调用子程序前,会先将CS入栈,再将IP入栈,调用时,SI入栈,结束前SI出栈,结束后,先IP出栈,再CS出栈。
如果你看懂了我上面所说的,你就可以自己画图了,如果没看懂,那么就说明你的基础太差劲,我画出图来你也不一定能看明白。
注意IP、CS、SI都是占两个字节,入栈时,高位先入,低位后入,出栈时相反,我看到前面有的人回答说还压入了ds,这是绝对不可能的。
跪望楼主加分!!拜托!!!
吻你。
顺祝万寿无疆!!
很对不起,我不是学这个语言的~~~
我是学pascal的;
这里引用一下:
程序很简单
1.程序功能就是计算字符串的长度,所以len为12,改变字符串长度len自然改变
2.实现的就是循环比较是否为-1来找到字符串长度。调用前后堆栈变化无非就是压入了ds,ip,si,返回时逆序释放
3.你随便定义个段名,如findlen,把那段程序放到该段里,然后去调用吧
回答者:desger - 经理 四级 12-11 19:35
如果说真是这样的话,在pascal 里也是很容易实现的,但是今天没有那么时间下次在发咯`~~~
程序很简单
1.程序功能就是计算字符串的长度,所以len为12,改变字符串长度len自然改变
2.实现的就是循环比较是否为-1来找到字符串长度。调用前后堆栈变化无非就是压入了cs,ip,si,返回时逆序释放
3.你随便定义个段名,如findlen,把那段程序放到该段里,然后去调用吧
劝你找本书好好看看,给别人看这种东西很费神啊,祝你进步!
真是晕阿
看在迷茫