与子程序毫无关系。
主程序结构有毛病,有二:
1、未给数据段、堆栈段寄存器赋值;
2、MOV BX,0B125H
CALL SHOWHEX
之后,未直接结束程序,而是又继续执行子程序。
只跟你说一下大体思想吧。其他的还是你自己作比较好。
1用指针SI和DI分别指向数据区和存储区首字节,则A2首地址为[SI+LENG],同样SUB1首地址为[DI+LENG]
然后用MOV AX,[SI];MOV BX,AX;ADD AX,[SI+LENG];MOV [DI],AX;MOV AX,BX;
SUB [SI+LENG];MOV [DI+LENG],AX然后指针后移ADD SI,2(如果是字节变量则为1)
2十进制转二进制就是用除2的办法。用DIV指令,对于字变量,商在AX中,余数在DX中。DX中的值只可能为1或0。再用SHR和ROR指令将DX的值移入寄存器BX中,注意所移动的位数。当AX中的值为1或0时,将其移入BX即结束。
显示的话,需将结果每一位转成ASCII码即可。
转八进制只需将转好的二进制从低到高三位一组转成ASCII码即可。还是使用移位指令,每次移三位即可。
push ax ; ax 的数据压入堆栈
pop ax ; 出栈 恢复 ax 数据
调用子程序前为了 保存 ax 的数据 不 受到影响,返回时 恢复原来的数据。
如果子程序不用到 ax 则可以 省去上述 *** 作。
CODE SEGMENT
ASSUME CS:CODE
ORG 100H
START: PUSH CS
POP DS
PUSH CS
POP ES
MOV DI,0
MOV SI,0
MOV BX,10
@MAIN1: MOV CX,BX
CALL FACT
ADD SI,AX
ADC DI,DX
DEC BX
JNZ @MAIN1
MOV AX,SI
MOV DX,DI
CALL DISPDXAX
MOV AH,4CH
INT 21H
; cx中存放要求阶乘的数
; 阶乘结果在dx、ax中
FACT PROC NEAR
PUSH BX
PUSH SI
PUSH DI
PUSHF
MOV DX,0
MOV AX,1
@FACT1: MOV BX,CX
CALL MULT
LOOP @FACT1
POPF
POP DI
POP SI
POP BX
RET
FACT ENDP
; 将要显示的无符号数置于 ax 中
DISPAX PROC NEAR
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DS
PUSH CS
POP DS
MOV BYTE PTR NZ,0
PUSH AX
LEA SI,DIVARR
MOV CX,5
@1:
POP AX
MOV DX,0
MOV BX,[SI]
DIV BX
PUSH DX
CMP AL,0
JNE @2
CMP BYTE PTR NZ,1
JE @2
CMP CX,1
JE @2
MOV DL,20H
JMP @3
@2:
ADD AL,30H
MOV DL,AL
MOV BYTE PTR NZ,1
@3:
MOV AH,2
INT 21H
INC SI
INC SI
LOOP @1
POP DX
POP DS
POP SI
POP DX
POP CX
POP BX
RET
DIVARR DW 10000,1000,100,10,1
NZ DB 0
DISPAX ENDP
; 无符号乘法子程序 (mul指令只能实现16位乘16位,本子程序实现32位乘16位--限定数的大小,结果仍为32位)
; 被乘数放置于dx,ax 中, 乘数放置于 bx中
; 结果放置于dx,ax中(dx为高16位,ax为低16位)
MULT PROC NEAR
PUSH CX
PUSH SI
PUSH DI
PUSHF
MOV SI,0
MOV DI,0
CMP BX,0
JE @MULTEXIT
@MULT1: SHR BX,1
JNC @MULT2
ADD SI,AX
ADC DI,DX
@MULT2: SHL AX,1
RCL DX,1
CMP BX,0
JNE @MULT1
MOV DX,DI
MOV AX,SI
POPF
POP DI
POP SI
POP CX
RET
@MULTEXIT:
MOV AX,0
MOV DX,0
POPF
POP DI
POP SI
POP CX
RET
MULT ENDP
; 将要显示的32位无符号数置于dx、ax中
DISPDXAX PROC NEAR
MOV WORD PTR [Y],AX
MOV WORD PTR [Y+2],DX
; 以下将 Y (16进制)转为10进制串并输出
MOV AX,WORD PTR [Y] ;=====
MOV DX,WORD PTR [Y+2] ;=====
MOV BX,WORD PTR [Z] ;===== 这一段是关键,加上后不会出现除法溢出
MOV CX,WORD PTR [Z+2] ;=====
MOV WORD PTR N,0 ;=====
MM0: INC WORD PTR N ;=====
SUB AX,BX ; 不停地减 10万 ,得到被10万除的商,放在 n 中
SBB DX,CX ;=====
JNC MM0 ;=====
DEC WORD PTR N ; 保存 高5位
ADD AX,BX ;=====
ADC DX,CX ;=====
MOV WORD PTR[Y],AX ;=====
MOV WORD PTR[Y+2],DX ;=====
;==============
MM1: LEA DI,CC
ADD DI,9
M2:
MOV AX,WORD PTR [Y]
MOV DX,WORD PTR [Y+2]
MOV BX,10000
DIV BX ; 这里是发生溢出之处
PUSH AX
PUSH DX
; ============
; 以下转换10进制的低4位
POP DX
MOV CX,4
MOV AX,DX
M3: MOV DX,0
MOV BX,10
DIV BX
ADD DL,30H
MOV [DI],DL
DEC DI
LOOP M3
; ===========
; 以下转换10进制的高万位
POP AX
MOV CX,1
M4: MOV DX,0
MOV BX,10
DIV BX
ADD DL,30H
MOV [DI],DL
DEC DI
LOOP M4
;=============
MOV AX,WORD PTR N
MOV CX,5
M5: MOV DX,0
MOV BX,10
DIV BX
ADD DL,30H
MOV [DI],DL
DEC DI
LOOP M5
; ============
; 输出换行回车
LEA DX,LFCR
MOV AH,9
INT 21H
; ============
; 输出两数的和的10进制串
LEA DX,CC
MOV AH,9
INT 21H
RET
Y DD
CC DB 10 DUP(' '),10,13,'$'
LFCR DB 10,13,'$'
Z DD 100000
N DW 0
DISPDXAX ENDP
CODE ENDS
END START
C
在一段汇编程序中多次调用另一段程序,用宏指令比用子程序实现占内存空间大,但速度快。
宏调用是通过宏扩展来实现的,宏引用多少次,就相应扩展多少次,所以,引用宏不会缩短目标程序;而子程序代码在目标程序中只出现一次,调用子程序是执行同一程序段,因此,目标程序也得到相应的简化。
扩展资料:
在用一种不熟悉的宏语言进行宏编程时,可以这样做,首先记录下用户想要宏完成什么,然后打开宏文件并尝试理解命令结构如何工作。
也可以修改命令以调整宏。一些宏语言,比如Great Plains 会计软件的 Dexterity 运行时引擎,不能从其它数据源(如由逗号分隔的文本文件)导入数据。这一限制可以通过用更强大的编程语言,如VBA来创建一个计算机程序在此弱编程语言里生成一个特别的宏来解决。
参考资料来源:百度百科-宏命令
程序调用用call指令,调用的子程序必须已经写在程序里。
系统会自动把子程序的返回地址(即调用程序中call指令的下一条指令的地址)存入堆栈,子程序执行后也会自动把堆栈中存的地址取出。
以上就是关于汇编子程序调用及返回全部的内容,包括:汇编子程序调用及返回、汇编语言(用子程序调用来编程的问题!)、汇编语言调用子程序前为什么要push ax,之后再pop ax等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)