第六章 子程序程序设计
汇编语言程序设计第6章

第6章 子 程 序 设 计
该指令先把返回地址(即主程序中CALL指令的下一条指令 的地址)保存到堆栈中,以便子程序执行完返回主程序时使用, 然后则转移到子程序的入口地址去执行子程序。指令中的DST 一般是过程名(被调用过程),即子程序入口的符号地址,D16是 子程序入口地址和CALL指令之间的偏移量。
第6章 子 程 序 设 计 6.2.2 子程序调用方法说明
一个完整的子程序,应当包括子程序调用方法说明、保护现 场和恢复现场、子程序定义等部分。为了使用的方便,子程序应 以文件形式编写。子程序文件由子程序说明和子程序本身构成。 子程序说明部分要求语言简明、确切。
子程序说明一般由如下几部分组成: (1) 功能描述:包括子程序的名称、功能、性能指标(如执 行时间)等。 (2) 所用的寄存器和存储单元。 (3) 子程序的入口、出口参数。 (4) 子程序中又调用的其他子程序。 (5) 调用实例。
第6章 子 程 序 设 计
2.重复性 子程序是可多次重复使用的。—个子程序只占一段存储空 间,但可以多次地调用它,这样就避免了编程人员的重复劳动, 节省了存储空间。由于增加了调用、返回指令以及现场保护, 因此程序执行时间会增长。如果一个程序段只用到一次,就没 有必要编写成子程序形式。
第6章 子 程 序 设 计
RET SUBA ENDP SUBB PROC FAR
…
SUBB CODEB
RET ENDP ENDS END
MAIN
第6章 子 程 序 设 计
由于SUBB既被段间调用又被段内调用,所以必须是FAR属性。 例6-2给出的子程序SUBA、SUBB与主程序MAIN不在同一代码 段中,主程序MAIN在CODEA代码段中,而子程序SUBA、SUBB在 CODEB代码段中。 例6-1和例6-2说明,汇编语言程序中的主、子程序,既可 以在同一个代码段中(如例6-1),也可以在不同的代码段中(如 例6-2)。
《IBM PC 80X86汇编语言程序设计》PPT电子课件教案-第六章 子程序设计

《IBM PC 80X86汇编语言程序设计》
冶金工业出版社
第6章
1、子程序的概念和特点
子程序:把在程序中多次出现,具有独立功能 的程序段写成程序模块,该模块可被多次调用, 称之为子程序。
特点:①可重复使用(调用) ②具有通用性(可通过入口参数实现) ③可浮动性(存放位置灵活) ④可递归性和可重入性
第6章
第六章 子程序设计
一、子程序的定义 二、子程序的结构形式
三、子程序的设计和调用 四、子程序的参数传递方法 五、子程序的嵌套和递归调用 六、子程序的设计举例 七、多模块程序设计 八、汇编语言和高级语言的混合编程
《IBM PC 80X86汇编语言程序设计》
冶金工业出版社
第6章
一、子程序的定义
1、子程序的概念和特点 2、子程序的定义 3、子程序的调用和返回
《IBM PC 80X86汇编语言程序设计》
冶金工业出版社
第6章
2、子程序的定义
子程序的定义是由过程定义伪指令PROC和ENDP 来完成的。其格式如下:
过程名 PROC [NEAR/FAR]
┆
过程名 ENDP
其中PROC表示过程定义开始,ENDP表示过程定 义结束。过程名是过程入口地址的符号表示。
一般过程名同标号一样,具有三种属性,即段 属性、偏移地址属性以及类型属性。
《IBM PC 80X86汇编语言程序设计》
冶金工业出版社
第6章
3、子程序的调用和返回
❖ 调用
①段内直接调用
格式:CALL 子程序名
功能:将子程序返回地址(断点)入栈
SP←SP-2
(SP)←IP,
并转到子程序入口地址去执行子程序。
❖ 返回指令
实验六循环子程序结构程序设计

36E6:002C 75F8 JNZ 0026
36E6:002E C3 RET 一 G=0 C ;观察第一次求和,DH=06H AX=0300 BX=0600 CX=032F DX=0600 SP=0000 BP=0000 SI=0000 DI=0000
DS=2000 ES=36D6 SS=36E6 CS=36E6 IP=000C NV UP EI PL ZR NA PE NC
B44C MOV AH,4C 2CA2:0034 CD21
INT 21 一 g=0 32
AX=0403 BX=0300 CX=0000 DX=0000 SP=0000 BP=0000 SI=000A
第六章子程序设计

MOV DL, ’P’ MOV AH, 2 INT 21H RET DISP ENDP CODE2 ENDS
END START
2023/12/31
汇编语言程序设计教程
12
例:段间间接调用
DATA SEGMENT NUM DW 1 CAADDR DW OFFSET SUBRT0
2023/12/31
汇编语言程序设计教程
23
6.3 子程序的嵌套与递归
6.3.1 子程序的嵌套调用 6.3.2 子程序的递归调用
2023/12/31
汇编语言程序设计教程
24
子程序的嵌套调用
• 子程序内包含有子程序的调用就是子程序的嵌套。嵌套深 度(即嵌套的层次数)逻辑上没有限制,但由于子程序的 调用需要在堆栈中保存返回地址以及寄存器等数据,因此 实际上受限于开设的堆栈空间。
• 子程序处理完数据后,将执行结果作为出口参数 存入寄存器中。
• 返回主程序后,主程序对存放在寄存器中的出口 参数进行相应的处理。
• 用寄存器传递参数方便、直观,是经常使用的方 法。但能传递的参数有限,适于参数较少的情况。
2023/12/31
汇编语言程序设计教程
21
通过堆栈传递参数
• 通过堆栈传递参数的思想是:主程序把入 口参数入栈保存,然后调用子程序,子程 序从堆栈中弹出入口参数进行处理。
• 递归子程序必须采用寄存器或堆栈传递参数,递归深度受 堆栈空间的限制。
• 递归子程序对应于数学上对函数的递归定义,它往往能设 计出效率较高的程序,可以完成相当复杂的计算。
2023/12/31
汇编语言程序设计教程
返回
第六章子程序

(即当前的CS、IP)
b、将过程名的
偏移量
段地址 偏移量
堆栈
CS IP
RET
A、NEAR B、FAR
将栈顶一个字的内容 将栈顶两个字的内容
IP IP、CS
(二)完整的主程序及子程序的结构形式 1、近过程 CODE ASSUME START:MOV MOV MOV …… SEGMENT CS: CODE ,DS:DATA DS ,AX ES,AX AX,DATA
与主程序不在同一段CS不同
……
过程名 ENDP
2、调用和返回指令及功能
(1)指令
CALL
RET
A、近过程 B、远过程
CALL CALL
过程名 FAR PTR 过程名
(2)功能: CALL 过程名
A、若过程名为NEAR属性 a、将断点的偏移量 (即当前的IP) b、将过程名的偏移量 IP 堆栈
(寄存器、存贮器) B、若过程名为FAR属性a、将断点的地址 段地址
CALL ……
过程名(字程序名)
MOV INT 过程名 PORC …… RET 过程名 ENDP CODE END 2、远过程
AH,4CH 21H (NEAR)
ENDS START
CODEI SEGMENT ASSUME CS:CODEI ,DS:DATA
START: MOV MOV AX,DATA DS, AX
子程序
子程序又称过程,相当于高级语言中的过程和函数,在一个程序中多次用 到一个程序段。这个程序段的功能和形式都相同,只是某些变量的赋值不 同,可以把这些程序段写成子程序的形式,以便需要时调用。 (一)子程序(过程)的定义、调用和返回指令 1、过程(子程序)的定义伪指令 NEAR 过程名 PROC Attribute 或FAR 与主程序在同一段CS相同
语言程序掌握子程序的设计

语言程序掌握子程序的设计
1.定义子程序
子程序是一种由一系列指令组成的程序单元,它不能独立执行,而是在主程序中被调用,完成特定功能。
它常常由多个步骤组成,每个步骤完成特定的工作,并接受传入的参数值,以便实现代码复用。
2.子程序的优点
子程序有以下优点:
(1)节省内存:存储程序的代码时,每个子程序只需要一次存储,只要在主程序中调用,就可以运行。
因此,节省了大量的存储空间,能够有效的提升程序的执行效率。
(2)提高程序的可读性:当程序中有很多功能,用子程序的方式将功能拆分开来,方便阅读和编写程序,提高了程序的可读性。
(3)提高程序的重用性:由于子程序可以通过一次存储,可以无限次调用,因此可以大大提升程序的重用性,减少编程的重复工作量。
(4)代码可维护性:由于子程序只执行特定功能,代码量比较小,因此可以有效的提高代码维护的效率,对代码进行修改和改进。
3.子程序的编写
(1)定义子程序的参数:在编写子程序前,需要先定义子程序的参数,包括参数的类型、个数、变量名等。
(2)编写子程序的步骤:根据参数、功能定义,编写具体的步骤,完成子程序的编写。
汇编语言程序 掌握子程序的设计

汇编语言程序掌握子程序的设计汇编语言程序掌握子程序的设计什么是子程序子程序是汇编语言中一种独立的可重复使用的程序代码片段,它可以被主程序调用和执行。
子程序的设计可以让程序更加模块化,提高代码的复用性和可维护性。
子程序的设计原则1. 单一职责原则:每个子程序只负责一个特定的任务,功能要清晰明确,只有一个明确的入口和出口。
2. 低耦合原则:子程序之间应该尽量少的依赖和耦合,可以独立进行调试和修改,互相之间不会产生影响。
3. 高内聚原则:子程序内部的代码要高度集中和相关联,功能相关的代码应该放在一起。
4. 应该尽量避免代码的冗余和重复,可以将常用的代码片段封装成子程序,提高代码的可维护性和可读性。
子程序的设计步骤1. 确定子程序的功能和功能的输入输出:明确子程序的任务和需要的输入参数,确定子程序的输出结果。
2. 设计子程序的接口和入口参数:确定子程序的调用方式和输入参数的传递方式,以及子程序返回结果的方式。
3. 编写子程序代码:根据子程序的功能和接口的要求,编写相应的汇编语言代码。
4. 调试和测试子程序:进行子程序的单独测试和调试,确保子程序的功能正确和稳定。
5. 在主程序中调用子程序:将子程序集成到主程序中,并按照子程序的接口要求传递参数并获取结果。
子程序的设计案例:计算阶乘假设我们需要在汇编语言中设计一个子程序,用于计算给定整数的阶乘。
assemblysection .datanum db 5result dw 0section .textglobal _start_start:mov al, te [num]call factorialmov word [result], ax ; 其他指令factorial:push bpmov bp, sppush axpush cxxor ax, axmov cl, alcmp al, 1je end_factorialdec alcall factorialmul clend_factorial:pop cxpop axpop bpret在上面的例子中,我们使用了一个子程序`factorial`,用于计算给定整数的阶乘。
微机原理与应用第六章

数组字<AX? N 内容交换 修改数组指针 N 到100字?
YRT: MOV MOV MOV MOV MOV NEXT1: CMP
AX,2000H DS,AX BX,0042H AX,0 CX,100 AX,[BX]
循环次数已知 (计数控制)
JA
MOV NEXT: INC
NEXT
MAX PROC NEAR PUSHF PUSH AX PUSH CX PUSH SI
STAR:MOV BX,2000H MOV AL,5 MOV AH,0 [BX+AL] XLAT HLT ADD BX,AX
MOV AL,[BX] 执行后:AL=19H
复习换码指令
…… 64H 51H 40H 31H 24H 19H 10H 09H 04H 01H 00H
⑴ 段内直接调用与返回
格式:CALL 过程名 功能:调用当前段内的子程序 操作:SP←SP-2,[SP]←IP,IP←IP+disp 格式:RET 操作:IP ←[SP],SP← SP+2 16位通用寄存器或 ⑵ 段内间接调用与返回 字存储器 格式:CALL OPRD 操作:SP←SP-2,[SP]←IP,IP←(OPRD) 格式: RET 操作:IP ←[SP],SP← SP+2
子 程 序 段
子 程 序 段
subr1 proc near ...... ret subr1 endp main endp code ends
主 程 序 段
code ends
例:
MY SEGMENT ASSUME CS:MY MAIN PROC FAR START: PUSH DS SUB AX,AX PUSH AX MOV CL,04 CALL DP5 MOV BL,CL CALL DP5 ADD AL,BL RET MAIN ENDP DP5 PROC MOV SAL SAL ADD MOV NEAR AL,CL AL,1 AL,1 AL,CL CL,AL
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
4. 结构伪指令
• 到目前为止,允许分配和命名指定大小(字节、字和双字等)的变量的 指令,但大多数应以程序是使用相关的变量组而非单个变量。例如保存 人名的一个应用程序,如果该程序要保存人的最后名、最初名和中间的 词首分隔符,每个名是三个独立的文本串。可以使用独立的BYTE指令 来分配每个串,但将这三个串放在一起作为一组分配是方便的。MASM 中的STRUC指令正好提供这种功能——定义一个由(可能是)• 不同类 型变量组成的整体数据结构。 • 使用STRUC组织用户数据 • 为结构分配空间 • 在汇编过程中初始化结构域 • MASM中嵌套的结构 • 访问结构中的域 • 访问嵌套结构中的域 • 返回
CALL指令祥解
• 段内调用:
– 直接调用
• CALL <过程名>
–ቤተ መጻሕፍቲ ባይዱ间接调用
• • • • CALL CALL CALL CALL reg /mem BX CX WORD PTR 20H[BX][SI]
– 如果在段内调用远过程
• CALL FAR PTR <过程名>
•
返回
2. 子程序的结构类型
1. 2. 3. 4. 5. 6. 7.
1. 定义子程序的伪指令
子程序的结构如下: <子程序名> PROC [NEAR/FAR] … RET [n] … <子程序名> ENDP 调用指令: CALL <子程序名> 子程序的类型有NEAR和FAR(缺省为NEAR)• ,和调用程序在同一代码 段中的子程序用NEAR,和调用程序不在同一代码段中的子程序使用 FAR属性,当然定义为FAR的子程序在同一段也可调用。 在执行CALL语句时,将CALL语句的下一语句的IP(或CS和IP)压栈, 在执行子程序时中的RET[n]语 • 句时,系统将用栈顶的内容弹出并更新IP (或IP和CS)的值,若有[n]系统将再多弹出n个字节(n必须为偶数)。 • 返回
10) 11)
返回
代码转换举例
• • • • • • • • • • • • • • • • • • • • • • DEC_BIN PROC FAR ;BX中存放从键盘输入的十进制数转换的二进制数 MOV BX,0 ;BX中存放输入的数值 NEWCHAR: MOV AH,01H INT 21H ;(al)为ASCII字符 SUB AL,30H ;ASCII TO binary JL EXIT ;jump if <0 CMP AL,0AH ;is it >9d? JGE EXIT ;yes not decimals digit CBW ;byte in AL to word in AX ;digit is now in AX ;将BX乘上10 XCHG AX,BX ;exchange ax and bx MOV CX,10 ; MUL CX ;将AX乘上10 ADD BX,AX ;将AX与BX相加并送BX JMP NEWCHAR ;get next digit EXIT : RET DEC_BIN ENDP 返回
⑴ 一个主程序调用一个子程序
⑵ 多层嵌套调用:
子程序再调用子程序,要格外注意程序中的堆栈变化,要确 保子程序在每次返回时,SP指向的是正确的返回地址,而不 是数据或其它信息。 ⑶ 递归调用子程序: 子程序调用自身,这种结构程序短效率高,它是嵌套调用的 一种特殊情况 返回
3. 子程序的数据传送方法
通常有五种方法: ⑴ 直接访问: 子程序和调用程序在同一程序模块中,则子程序可直接访问模块中的 变量 ⑵ 使用PUBLIC定义的公共(全局)变量和EXTRN说明的外部变量。 ⑶ 通过寄存器 ⑷ 通过堆栈 ⑸ 通过公共数据区 各模块分别定义一个同名的数据段,并用组合类型COMMON合并为 一个覆盖段,这样变量即成为本模块的局部变量,可直接引用。 • 返回
十二算法
• 思路:
123=1*100+2*10+3 =(((0*10)+1)*10+2)*10+3 X=X*10+Y
•
算法:
1) 2) 3) 4) 5) 6) 7) 设BX中存放最终二进制数,初值为0 从键盘输入一个字符,如1,则(al)中为其ASCII AL(AL)-30H ;将ASCII变成实际的数值 判断0<=(AL)<=9?,不是转7) 执行CBW命令将ALAX BX(BX)*10+AX,转2) 结束
为结构分配空间
• 前面的定义只是为该结构定义了一个模板,• 但MASM 还未分配空间。• 用户可以为FullName数据结构和其它 数据类型的实例分配空间并加以初始化。• 下面的例子 创建FullName结构的两个实例,• Naba和Mitch,还创建 含有10个FullName结构的数组,它可以通过People进行 访问。 • Naba FullName {} • Mitch FullName {} • People FullName 10 dup({}) • 返回
• • • • • • • • •
MASM中嵌套的结构
• MASM允许用户对结构定义进行嵌套,在一些情况下,这就允许 一个结构的某些域是结构本身。例如: • point STRUC • x db ? • y db ? • point ENDS • Rectangle STRUC • UpperLft point ;左上角坐标(x,y) • LowerRt point ;右上角坐标(x,y) • Rectangle ENDS • 返回
第六章 子程序程序设计
• 在一个程序中,当不同的地方需要多次使用的某程序段 (即完成一个给定功能的程序段)常常单独编制一指令序 列。在程序运行时,若需要这个给定功能,就转移到这个 指令序列,待指令执行完后,又返回到原来位置继续执行。 这个单独编制的指令序列就叫子程序,转移到子程序称为 调用子程序。 定义子程序的伪指令 子程序的结构类型 子程序的数据传送方法 结构伪指令 代码转换 递归程序设计 多模块之间的连接
代码转换举例
BIN_DEC PROC FAR MOV CX,10000D ;DEVIDE BY 10000 CALL DEC_DIV MOV CX,1000D ;DEVIDE BY 1000 CALL DEC_DIV MOV CX,100D ;DEVIDE BY 100 CALL DEC_DIV MOV CX,10D ;DEVIDE BY 10 CALL DEC_DIV MOV CX,1D ;DEVIDE BY 1 CALL DEC_DIV RET BIN_DEC ENDP ;-----------------------------------------------------------------------DEC_DIV PROC NEAR ;打印商到屏幕上 ;被除数在(DX,AX)里,除数在CX中 MOV AX,BX MOV DX,0 ;将高字赋0 DIV CX MOV BX,DX ;余数在BX中 MOV DL,AL ;商在DL中 ;显示DL到屏幕上 ADD DL,30H ;转换成ASCII MOV AH,02h ;INT 21H的02号功能显示DL中的ASCII到屏幕上 INT 21H RET DEC_DIV ENDP
使用STRUC组织用户数据
• 使用STRUC组织用户数据很容易,• 例如定义一个包含 最初名、最后名和中间分隔符的结构FullName,可以 使用代码: FullName STRUC Firstname db 15 dup(?) Initial db ? LastName db 24 dup(?) FullName ENDS • 结构定义并不占用空间,但MASM在遇到结构中的 域时就会为它分配空间。 • 返回
访问结构中的域
• • • • • • • • • • • • 当用户说明了某种结构类型的变量时,MASM将结构的第一字节的偏移设 置为该变量名,用户可以使用地址表达式了访问该结构的域。访问方式: <变量名>[位移量] <变量名>.<域名> 例: MOV al,Naba+15 MOV al,Naba.Initial MOV al,Naba.Firstname[4] LEA si,stname 若将Naba的地址已被装入ES:[BX]中,如果要访问LastName,使用指令 MOV al,ES:[BX].Lastname 若Lastname是由几个结构共享的域名,将会发生错误。 返回
–
算法及思路
•
• • • •
二 十: 向屏幕输出时,通常输出十进制数,因为符合人们的习惯,但在计算机内部为十六 进制,如将7BH输出到屏幕,必须将其化成十进制数123的ASCII码31H、32H、 33H再分别输出到屏幕。使用DOS中断的02号功能,显示字符到屏幕 mov ah,02h int 21H 算法与思路 举例: 十二 二十 返回
在汇编过程中初始化结构域
• • • • • • • • • 上例中用户说明结构变量时,• MASM并不初始化这些域为任何值(实际上为0)。用户也可在定义结 构时进行初始化: FullName STRUC Firstname db '---------------' Initial db '-' LastName db '------------------------' FullName ENDS 使用这种定义,则用FullName类型说明的任何变量在缺省时其中的域都初始化为短线。 如果用户所需的大多数(或所有的)结构都以相同的域值开始,那么缺省的初始化是很有用的。• 但 通常用户需要将每个结构实例初始化为不同的域值。• 例如上述的变量Naba和Mitch要包含类似于 "Naba"和"Mitchell"这样的串,• 而不是短线。MASM提供了使用指定值替换缺省值的手段。当定义一 个结构变量的实例时,可以在参数域的"{"和"}"(也可使用"< >")符号之间包含一个初始化表。 Naba FullName {"Naba"," ","Barkakati"} Mitch FullName {"Matchell"," ","Waite"} 用户可以只初始化结构中的某些域,如果初始化表中某一项为空,MASM就给该域使用缺省值。如: Jonathon FullName {"Johnny"} ;Initial/Lastname=-John FullName {,"A"} ;First/Lastname=-Jon FullName {,,"Apple"} ;First/Initial=--Johnny FullName {"John"," "} ;Last=----------返回