1 / 27

宏指令及其使用 宏指令、宏定义和宏调用 宏指令 源程序中具有独立功能的一段程序代码 宏定义 宏指令名 MACRO < 形式参数 > … ;

宏指令及其使用 宏指令、宏定义和宏调用 宏指令 源程序中具有独立功能的一段程序代码 宏定义 宏指令名 MACRO < 形式参数 > … ; … 宏体 … ; ENDM 宏调用 宏调用的格式为: 宏指令名 < 实际参数 >. 例: 1 ) PUSHREG MACRO PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI

devlin
Download Presentation

宏指令及其使用 宏指令、宏定义和宏调用 宏指令 源程序中具有独立功能的一段程序代码 宏定义 宏指令名 MACRO < 形式参数 > … ;

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 宏指令及其使用 • 宏指令、宏定义和宏调用 • 宏指令 源程序中具有独立功能的一段程序代码 • 宏定义 宏指令名 MACRO <形式参数> … ; … 宏体 … ; ENDM • 宏调用 宏调用的格式为: 宏指令名<实际参数>

  2. 例: 1)PUSHREG MACRO PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI ENDM 2)LOADW MACRO PR,VAR MOV PR,VAR MOV AX,[PR] ENDM 3)SHIFT MACRO N,REG,CC MOV CL,N S&CC REG,CL ENDM 4)SAVEW MACRO PR,REG,OPC MOV [PR],REG OPC PR ENDM LOADW SI,WVAR SHIFT 4,AX,AR SAVEW SI,AX,INC … 将某变量指针WVAR指向的内存单元的内容送AX寄存器。右移4位后,再存入WVAR变量处。

  3. 宏嵌套 … MULTIPLY FIRST1,FIRST2,MULT1 +MOV AL,FIRST1 +IMUL FIRST2 +MOV MULT1,AX MULTIPLY SECOND1,SECOND2,MULT2 +MOV AL,SECOND1 +IMUL SECOND2 +MOV MULT2,AX ADDMULT AX,MULT1,MULT2 +MOV AX,MULT1 +ADD AX,MULT2 +MOV SUM,AX … MULTIPLY MACRO OPR1,OPR2,RESULT MOV AL,OPR1 IMUL OPR2 MOV RESULT,AX ENDM ADDMULT MACRO REG,VAR1,VAR2 MULTIPLY FIRST 1,FIRST2,MULT1 MULTIPLY SECOND1,SECOND2,MULT2 MOV REG,VAR1 ADD REG,VAR2 MOV SUM,REG ENDM 宏调用: ADDMULT AX,MULT1,MULT2

  4. DELAY 6789H,0FFFFH + PUSH AX + PUSH CX + MOV CX,6789H +??0000:MOV AX, OFFFFH +??0001 DEC AX + JNZ ??0001 + LOOP ??0000 + POP CX + POP AX … DELAY 0FFF0H,8000H + PUSH AX + PUSH CX + MOV CX,0FFF0H +??0002:MOV AX,8000H +??0003:DEC AX + JNZ ??0003 + LOOP ??0002 + POP CX + POP AX • 宏定义中的标号与变量 DELAY MACRO VALUE1,VALUE2 LOCAL AGAIN1,AGAIN2 PUSH AX PUSH CX MOV CX,VALUE1 AGAIN1: MOV AX,VALUE2 AGAIN2: DEC AX JNZ AGAIN2 LOOP AGAIN1 POP CX POP AX ENDM 宏调用: … DELAY 6789H,0FFFFH … DELAY 0FFF0H,8000H …

  5. 小结 • 宏指令与子程序的异同 • 相同点:均可用来简化源程序,并可使程序对它们多次进行调用。 • 不同点: • 定义方法及格式不同。 • 子程序省内存,宏指令则不省。 • 子程序执行速度慢,而宏运行速度快。

  6. 6.2 汇编语言程序设计 编制汇编程序步骤: • 明确任务,确定算法 • 绘流程图 • 根据流程图编写汇编语言程序 • 上机调试程序 程序的基本结构: • 顺序结构 • 分支结构 • 循环结构 • 子程序结构

  7. EDIT ABC.ASM 编辑源程序 MASM ABC.ASM 汇编源程序 Y 有汇编错误信息 ? N ABC.OBJ 形成目标程序 连接目标程序 LINK ABC.OBJ Y 有连接错误信息 ? N 形成可执行程序 ABC.EXE 装入可执行程序到内存 并执行 ABC Y 运行结果正确 ? 下一程序 N N DEBUG ? 用 调试程序查错 Y DEBUG 用 调试可执行程序 找到原因 DEBUG ABC.EXE

  8. 1.顺序程序设计 例: TITLE EXAMPLE 1 DATA SEGMENT 2 VARX DW 6 3 VARY DW 7 4 RESULT DW ? 5 DATA ENDS 6 STACK1 SEGMENT PARA STACK 7 DW 20H DUP(0) 8 STACK1 ENDS 9 COSEG SEGMENT 10 PROC1 PROC FAR 11 ASSUME CS:COSEG,DS:DATA,SS:STACK1 12 START: PUSH DS 13 MOV AX,0

  9. 续: • 14 PUSH AX • 15 MOV AX,DATA • 16 MOV DS,AX • 17 MOV DX,VARX ;DX←X • 18 ADD DX,VARY ;DX←(X+Y) • 19 MOV CL,3 • 20 SAL DX,CL ;DX←(X+Y)*8 • 21 SUB DX,VARX ;DX←(X+Y)*8-X • 22 SAR DX,1 ;DX←((X+Y)*8-X)/2 • 23 MOV RESULT,DX ;存结果 • 24 RET • 25 PROC1 ENDP • 26 COSEG ENDS • END START • 源程序代码段中: • 第15,16语句是为数据段寄存器赋值,让DS指向本程序的数据段DATA。 • 第17~第23语句完成公式计算并存储结果是代码段中。 • 第12~第14语句是为用户程序结束,返回DOS操作系统而作的准备。

  10. DOS的装入功能 (又称EXEC系统功能) • 可执行文件.exe,应装入内存方能执行。 • 由DOS的装入功能完成。 • 在DOS的提示符后输入可执行文件的文件名, • 按回车键,DOS系统即调用装入功能 , • 将可执行程序装入内存。

  11. 当一个用户程序的可执行文件(.EXE)装入内存后,存储器分配情况如图所示当一个用户程序的可执行文件(.EXE)装入内存后,存储器分配情况如图所示 0H DS,ES 共100H个字节 SS 用户空间 CS 0FFFFFH

  12. 存 0000: 0000H 1KB 中断向量表 DOS 系统 COMMAND.COM xxxx: 0000H CD 20 … 程序段前缀 … … 可用 xxxx: 00FFH 内存 用户程序 hello.exe 空间 ROM BIOS FFFF:0000H 系统检测程序 • 完成以下操作: • 确定内存可用部分, • 以便存放要执行的 .exe 文件。 • 建立程序段前缀PSP • (Program Segment Prefix) • 程序段前缀大小100H, • 即256个字节。 • 存放进程间的控制信息。 • PSP最开始的两个字节CD 20, • 是一条 INT 20H指令。 • 装入可执行程序.exe

  13. 存 0000: 0000H 1KB 中断向量表 DOS 系统 COMMAND.COM xxxx: 0000H CD 20 … 程序段前缀 … … 可用 xxxx: 00FFH 内存 CS:IP hello.exe 空间 ROM BIOS FFFF:0000H 系统检测程序 • 修改以下寄存器的值 • DS、ES设置为 • 程序段前缀所在内存的段值; • (DS)=xxxxH • (ES)=xxxxH • SS、SP 设置为 • 由连接程序传过来的值; • CS、IP 设置为 • 程序的入口地址, • 即伪操作END后跟的 • 符号名对应的物理地址; • 此时 CS:IP 指向用户程序, • 开始执行用户程序。

  14. 20H 中断程序的功能: • 处理程序结束,返回系统。 • 调用20H中断程序是有条件的: • 要求当前的CS应为程序段前缀在内存的段值

  15. CD 20 xxxx:0 程序段 PSP 前缀 …. 用户程序 0000 PSP 的偏值 SS:SP xxxx PSP 的段值 SS:SP CS IP • 采用下面的程序框架, • 可保证执行INT 20H时, • 当前的CS值为程序段前缀在内存的段值。 • code SEGMENT • ASSUME CS:code • main PROC FAR ;使RET为远返回 • start: PUSH DS ;入栈保存地址 • MOV AX, 0 ;程序段前缀的首地址 • PUSH AX • … ;程序主体部分 • … • RET ;取程序段前缀首地址 • main ENDP • code ENDS • END start

  16. 注意: 不可在汇编语言程序的最后用 INT 20H返回DOS。原因是20h中断子程的执行是有条件的。采用上述返回DOS的程序结构,才能满足该条件,否则无法返回。

  17. 结束用户程序,返回操作系统的另一个办法是用中断指令“INT 21H”。如使用这种办法,用户程序可以不设置过程,只要在用户程序结束时,用以下两条指令即可: MOV AH,4CH INT 21H 这样,上述程序的代码段可以修改为: COSEG SEGMENT ASSUME CS:COSEG,DS:DATA ASSUME SS:STACK1 START: MOV AX,DATA MOV DS,AX MOV DX,VARX ADD DX,VAY MOV CL,3 SAL DX,CL SUB DX,VARX SAR DX,1 MOV RESULT,DX MOV AH,4CH INT 21H COSEG ENDS END START

  18. 多个分支 Y N 两个分支 2.分支程序设计 分支程序结构也称条件结构,通常有两种形式,见图。

  19. 例:求补码数[X]补的绝对值,并送回原处。 STACK SEGMENT STACK ;定义堆栈段, DW 256 DUP(?) ;预留256个单元 TOP LABEL WORD STACK ENDS DATA SEGMENT XADR DW 3456H ;设[X]补=3456H DATA ENDS CODE SEGMENT MAIN PROC FAR ASSUME CS:CODE,DS:DATA,SS:STACK START: MOV AX,STACK ;将堆栈段段址送SS。 MOV SS,AX MOV SP,OFFSET TOP ;设置栈指针,使其指向栈顶地址。 PUSH DS ;将PSP中INT 20H指令的存放地址压入栈。 MOV AX,0 PUSH AX MOV AX,DATA ;将数据段段址送DS。 MOV DS,AX MOV AX,XADR ;取[X]补到AX。 AND AX,AX;设置标志位。 JNS DONE;若X≥0,转DONE。 NEG AX;若X<0,求补得|X|。 MOV XADR,AX;将|X|送回原处。 DONE: RET ;返回PC-DOS状态。 MAIN ENDP CODE ENDS END START

  20. 例:设有一组(8个)选择项存于AL寄存器中,试根据AL中哪一位为1把程序分别转移到相应的分支去。 BRANCH_ADDR SEGMENT ;定义数据段。 BRANCH_TAB DW ROUTINE1 ;定义数据表(跳转表)。 DW ROUTINE2 DW ROUTINE3 DW ROUTINE4 DW ROUTINE5 DW ROUTINE6 DW ROUTINE7 DW ROUTINE8 BRANCH_ADDR ENDS

  21. 续: ROUTINE_SELECT SEGMENT ;定义代码段。 MAIN PROC FAR ASSUME CS:ROUTINE_SELECT,DS:BRANCH_ADDR START: PUSH DS ;将PSP中INT 20的存放地址压入栈顶。 SUB BX,BX PUSH BX MOV BX,BRANCH_ADDR MOV DS,BX CMP AL,0 ;判AL中是否有置1的位。 JE DONE ;若AL全零,及早退出选择结构。 LEA BX,BRANCH_TAB ;跳转表首址送BX。 COUTINUE: SHR AL,l ;AL最低位移至CF。 JNC NOT_YET ;CF=0,转去检查下一位。 JMP WORD PTR [BX] ;CF=1,转相应分支程序。 NOT_YET: ADD BX,TYPE BRANCH_TAB ;修改BX内容,为转入下一分支作好准备。 JMP COUTINUE ;继续检查下一选择项。 DONE: RET ;若无选择项置位转此处,执行其它程序。 ROUTINE1: … ROUTINE2: … … … RET MAIN ENDP ROUTINE_SELECT ENDS END START

  22. 循环初始设置 循环体 循环初始设置 N N 循环条件判断? 循环条件判断? Y Y 循环体 3.循环程序设计 常见的循环程序结构有两种:WHILE_DO结构和DO_UNTIL结构,见图。 当型循环 (当条件成立进入循环) 直到型循环 (直到条件成立退出循环)

  23. 例:将内存的二进制数转化成以压缩的BCD码形式存储的十进制数。 .MODEL SMALL .386 DATA SEGMENT BINNUM DD 12345678H ;内存中的二进制数。 DECINUM DB 5 DUP(0) ;转化成压缩的BCD码的存储区。 NUMBER DD 1000000000,100000000,10000000,1000000 DD 100000,10000,1000,100,10,1 ;减数。 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA MAIN PROC FAR START: PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX ;初始化。 MOV EAX,BINNUM ;将数放入EAX。 MOV SI,OFFSET DECINUM ;SI指向BCD码存储区。 MOV DI,OFFSET NUMBER ;DI指向减数区。 MOV CX,5 ;循环5次。 ROTATE: CALL BINDECI ;调用二进制转化成十进制子程序。 ADD DI,8 ;DI下移两个双宇。 INC SI ;SI下移一个字节。 LOOP ROTATE ;若CX≠0则循环,输出下两位。 RET MAIN ENDP

  24. BINDECI PROC NEAR PUSHF PUSH CX ;入栈。 MOV CX,0 ;CX存放商,初始清0。 CLC ;清除CF。 DO_AGAIN1: SUB EAX,DWORD PTR[DI] ;EAX减去相应的减数。 JC NEXT1 ;若不够减,则跳出循环。 INC CL ;否则,CL加l(商)。 JMP DO_AGAIN1 ;继续减。 NEXT1: MOV CH,CL ;将商移入CH。 MOV CL,0 ;CL清0。 ADD EAX,DWORD PTR[DI] ;恢复最后一次减前的值。 CLC ;清除CF。 DO-AGAIN2: SUB EAX,DWORD PTR[DI+4] ;EAX减去下一个数。 JC NEXT2 ;若不够减,则跳出循环。 INC CL ;否则,CL加1(商)。 JMP DO_AGAIN2 ;继续减。 NEXT2: ADD EAX,DWORD PTR[DI+4] ;恢复最后一次减前的值。 ;CH:CL中放的是高两位商,是非压缩的BCD码。 ;以下将它们转化成压缩的BCD码并放入存储单元。 SHL CH,1 SHL CH,1 SHL CH,1 SHL CH,1 ;CH左移4位。 OR CH,CL ;CH中存放压缩的BCD码。 MOV BYTE PTR[SI],CH ;放入存储区。 POP CX POPF RET BINDECI ENDP CODE ENDS END START

  25. 例:将内存中以压缩的BCD码形式存储的十进制数转化成二制数 .MODEL SMALL .386 DATA SEGMENT BINNUM DD 0 DECINUM DB 12H,34H,56H,78H,90H ;用十六进制数表示压缩的BCD码。 DATA ENDS ;十进制数是1234567890。 CODE SEGMENT ASSUME CS:CODE,DS:DATA MAIN PROC FAR START: PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX ;初始化 MOV EAX,0 ;32位二进制数初始值为0。 MOV SI OFFSET DECINUM ;DS:SI指向 DECINUM。 MOV CX,5 ;循环5次。 ROTATE: CALL DECIBIN INC SI ;SI指向下一个字节 LOOP ROTATE MOV DWORD PTR BINNUM,EAX ;将32位二进制数放入 BINNUM。 RET MAIN ENDP

  26. DECIBIN PROC NEAR PUSHF PUSH ECX PUSH EBX BEGIN: MOV ECX,100 ;ECX放置乘数 100。 MUL ECX ;EAX乘100 MOV CH,BYTE PTR[SI] ;取出一个压缩的BCD码到CH。 MOV CL,CH ;复制到CL。 AND CL,0FH ;CL中保留低4位。 AND CH,0F0H ;CH中保留高4位,这时CH相当于非压缩的BCD码*16。 SHR CH,1 ;算术右移1位,相当于非压缩的BCD 码乘8。 MOV BH,CH ;移入BH暂时保存。 SHR CH,1 ;再算术右移1位。 SHR CH,1 ;再算术右移1位,相当于非压缩的 BCD码乘2 ADD CH,BH ;相当于非压缩的BCD码乘10。 ADD CL,CH ;加到CL上。 MOV CH,0 ;ECX保存两位BCD码转化成二进制数的结果。 ADD EAX,ECX ;加到EAX上去。 POP EBX POP ECX POPF RET DECIBIN ENDP CODE ENDS END START

  27. 气泡排序算法 DSEG SEGMENT ADDR DW N DUP(?) DSEG ENDS CSEG SEGMENT MAIN PROC FAR START:PUSH DS SUB AX,AX PUSH AX MOV AX,DSEG MOV DS,AX MOV CX,N ;内循环变量存于CX中,初值为N-l。 DEC CX LOOP1:MOV DI,CX ;外循环变量存于DI中,初值为N-l。 MOV BX,0 ;地址指针预置为0。 LOOP2:MOV AX,ADDR[BX] ;取相邻两数比较。ADDR[BX] CMP AX,ADDR[BX+2] JGE COTINUM ;若符合排列次序,转移。 XCHG AX,ADDR[BX+2] ;若不符合排列次序,二数交换。 MOV ADDR[BX],AX ;存大数。 COTINUE: ADD BX,2 ;修改地址指针。 LOOP LOOP2 ;若一遍未比较完,继续。 MOV CX,DI LOOP LOOP1 ;若N-l遍未作完,继续。 RET MAIN ENDP CSEG ENDS END START

More Related