|
本是
银牌会员
积分 2201
发帖 789
注册 2005-1-27
状态 离线
|
『楼 主』:
给宏汇编语言加入高级语言特性
给宏汇编语言加入高级语言特性:
程序控制IF/WHILE/UNTIL结构块 与
带参数表的PUSH/POP/CALL语句
汇编语言给人的感觉是充分的代码自由VS无限的责任,代码紧凑、运行速
度快,但缺少高级控制结构,子程序调用与现场处理的参数表传递冗长繁琐、
不直观,亲合力差。其实,通过宏汇编、重复汇编、数据结构、数据记录等高
级技术,选择一个功能比较完善的汇编例程库,完全可以实现汇编语言的高级
化界面。下面谈谈结构宏与栈宏。
===<<< 程序控制结构块 >>>===
┌────────────────────────┐
│ 程序控制能力增强,设计时有更多精力用于功能处理 │
│ 源程序中行标减少、按层嵌套,逻辑清晰、读写方便 │
└────────────────────────┘
[原有功能]
基于Davidson Corry(4610 SW Lander,Seattle,WA 98116,(206) 935-0244)
的SIT.INC,可称为“坐享”宏汇编程序控制结构块,实现高级语言程序控制结
构,一分支_IF.._ELSE.._ELSEIF.._ENDIF,二循环_WHILE..和.._UNTIL,甚至
有类似C语言的 _BREAK、_CoNTiNUe语句。借助这些程序控制结构块,汇编语言
源程序中可以大大减少跳转与循环的目标行标号的使用量,程序控制能力增强,
让程序员集中精力处理功能问题,方便自上而下逐步求精的结构化程序设计实践,
象高级语言一样地按层次缩进嵌套,逻辑清晰,读写方便。
原宏名及变量名起始符_可避免与MASM6.x内嵌宏名起始符.冲突,予以保留;
未设计的FOR循环、多分支CASE可通过已有循环语句和单分支_IF模拟实现。
[我的改进]
MS-DOS6.xx源码中 STRUC.INC对长跳转的处理巧妙自动测试跳转长度和前后
跳转,TASM编译器通过加入后置近距长跳转作为超长距离的长循环的LOOP目标巧
妙实现对长循环的处理,同时借用微软的长跳转判断,如此就增加了对>128字节
的长跳转循环的支持,且无需用户动手!当然,J和JN指令需重新定义为JMP xxx。
其它的优化还有:
改JNNcc/JNNNcc指令名宏定义法为EQU法,大大缩短了宏代码长度;
增加同义宏名_CONTINUE/_CONTICX/_UNTILCX/_ENDW,兼容MASM6.xx内嵌.指令;
增加JNCXZ/JNNNcc/JNN/JNNN宏定义,使跳转条件更完备,编译得以正常完成;
增加循环语句_WNTIL/_UHILE,使"当"、"到"有更多搭配,适合复杂的条件判断。
[程序控制结构的实质]--利于理解宏的参数
一言以蔽之,程序控制结构的实质就是:程序控制=跳转与循环的控制
从程序设计的角度看,程序的流程控制,就是跳转与循环目标(即行标)的
控制,实质是跳转与循环的操作引起标志寄存器的变化,而控制跳转与循环的
走向。
从非结化程序的结构化转换的角度看,当指令影响的寄存器标志成为跳转
(jmp/jcxz/j???)与循环(loop[n][e|z])的条件时,实施结构化转换。
[程序控制结构的类型及举例]--见“********************”后
===<<< 堆栈传参的压弹调用 >>>===
┌────────────────────────┐
│ 堆栈传参,同行同序,方便汇编处理现场、调用程序 │
└────────────────────────┘
由于汇编语言对PUSH/POP/CALL的规定,利用堆栈传递参数的程序中会见到如下
代码浪费源程序空间(指视觉上),子程序调用与参数表分离又不能象高级语言
一样直观清晰。
push bx
push cx
push dx
push si
;...
pop si
pop dx
pop cx
pop bx
push ax ; P5
push 16h ; P4
push 3Dh ; P3
push 0B4h ; P2
push 0F0h ; P1
call sub_035C
push ax ; P3
push word ptr [bp+P5] ; P2
push word ptr [bp+LOCAL_2] ; P1
call sub_048B
现在有了_PUSH/_POP/P0P/_CALL,你完全可以象高级语言一样地使用汇编语言!
上面的三段可以改成:
_push bx,cx,dx,si ;;压栈序(顺:末后)
;...
_pop bx,cx,dx,si ;;弹出序(反:末先)
; putpixel P1 x P2 y P3 c
_call sub_048B,<[bp+LOCAL_2]>,<[bp+P5]>,ax
; line x0 y0 x1 y1 c
_call sub_035C,0F0h,0B4h,3Dh,16h,ax
注意:
1) _PUSH/_POP成对使用,参数表同序,方便复制粘贴。如要顺序弹出,用_P0P:
_p0p si,dx,cx,bx ;;弹出序(顺:末后)
2)“_CALL 函数名,参数表”格式中参数压入序反:末参先入--变换时不要搞错!
参数可以是:直接数/寄存器/全局/局部变量(含offset loc_1)/主程序参数
这样的栈序方便理解/修改,编程效率高。
*****************************************************************************
[程序控制结构的类型及举例]
============================
[程序控制结构块的类型]
------------------------
判断:
~~~~~~
_IF
;
_ELSE
;
_ELSEIF
;
_ENDIF
_ELSEIF及_ELSE为另一情形,_IF结构为高级语言中所必备!
循环:
~~~~~~
0. 死循环(必须用_BREAK跳出!)
无测类
_REPEAT
;
_ENDW
1. “当”型(“当”条件成立,则执行循环体,否则执行循环外的语句)
前测类(最常用)
_WHILE
;
_ENDW
后测类
_REPEAT
;
_WHILE
2. “到”型(循环一直“到”条件成立即停止循环)
前测类
_WNTIL
;
_ENDW
后测类(最常用)
_REPEAT
;
_UNTIL
3. 混合型
双测类
_WHILE
;
_UHILE
_WNTIL
;
_UNTIL
_WHILE
;
_UNTIL
_WNTIL
;
_UHILE
4. LOOP型
_REPEAT (最常用)
;
_UNTILCX
_WHILE
;
_UNTILCX
_WNTIL
;
_UNTILCX
UNTILCX同UNTIL,但加上判断CX是否为0 (OR的关系,即条件为真或CX为0)
配合上述循环指令运用
_BREAK 可中止循环
_CONTINUE 可跳至循环开头
_CONTICX 可跳至循环开头(用于_UNTILCX循环中)
可在其后加上测试语句op,条件cnd(_CONTICX只加cnd),条件成立才动作
上述指令中_ELSE、_ENDIF不需要任何参数,
_UNTILCX、_CONTICX只要一个条件参数(=LOOPcc之cc),
其余需要测试语句(cmp等)和条件(=Jcc之cc)两个参数。
循环条件参数LOOPcc之cc:
Z/E NZ/NE 空白
影响寄存器标志的测试语句op列表:
SAHF POPF SHL/R RCL/R SAL/R ROL/R STC CLC CMC
NOT AND OR XOR TEST
NEG CMP[S] SCAS
ADD SUB ADC SBB INC DEC
REP
CALL
跳转条件参数Jcc之cc:
[[N]A/AE/B/BE/C/CXZ/E/G/GE/L/LE/O/P/PE/PO/S/Z]
[程序控制结构块的举例]--从非结构化程序段的结构化角度
======================================================
;_IF结构以CMP举例如下:
;-----------------------
;CMP
cmp ax,word ptr es:[1] _IF <cmp ax,word ptr es:[1]>,e
jne _02E8
;... ;...
_02E8: _ENDIF
;CMP放在_IF块前
cmp ax,word ptr es:[1] cmp ax,word ptr es:[1]
jne _02E8 _IF ,e
;... ;...
_02E8: _ENDIF
;CMP与J...之间有其它语句
cmp ax,word ptr es:[1] cmp ax,word ptr es:[1]
mov dx,offset _0888 mov dx,offset _0888
jne _02E8 _IF ,e
;... ;...
_02E8: _ENDIF
;分支_ELSE
cmp byte ptr ds:[0080h],0 _IF <cmp byte ptr ds:[0080h],0>,ne
je _0129
;... ;...
jmp short _0133
_0129: _ELSE
;... ;...
_0133: _ENDIF
;多分支_ELSEIF (也就是SWITCH...CASE)
cmp _0142,3 _IF <cmp _0142,3>,e
jne _037F
;... ;...
jmp short _0395
_037F: _ELSEIF <cmp _0142,4>,e
cmp _0142,4
jne _038B
;... ;...
jmp short _0395
_038B: _ELSEIF <cmp _0142,5>,e
cmp _0142,5
jne _0395
;... ;...
_0395: _ENDIF
;嵌套_IF
cmp al,'a' _IF <cmp al,'a'>,ae
jb _0484
cmp al,'z' _IF <cmp al,'z'>,be
ja _0484
;... ;...
_0484: _ENDIF
_ENDIF
;循环结构举例如下:
;-------------------
;WHILE型(CMP)
_05D4: _WHILE <cmp byte ptr [di],0>,ne
cmp byte ptr [di],0
je _05DC
inc di inc di
jmp short _05D4 _ENDW
_05DC:
;CMP实现的BREAK=C的BREAK或BASIC的EXIT FOR/DO/LOOP
_041D: _WHILE <cmp byte ptr [si],0>,a
cmp byte ptr [si],0
jbe _042A
cmp byte ptr [si],' ' _BREAK <cmp byte ptr [si],' '>,a
ja _042A
inc si inc si
jmp short _041D _ENDW
_042A:
;BREAK特例
repe cmpsb repe cmpsb
;... ;...
jz _0590 _BREAK ,e
;以UNTILCX回跳
mov si,[0081h] mov si,[0081h]
jcxz _027B _IF ,ncxz
_0270: .REPEAT
;... ;...
inc si inc si
loop _0270 .UNTILCX
_027B: _ENDIF
;以CONTINUE中途回跳
_0296: _REPEAT
;... ;...
test ax,ax _BREAK <test ax,ax>,z
jz _02C6
mov si,dx mov si,dx
cmp byte ptr [si],1Ah _BREAK <cmp byte ptr [si],1Ah>,e
je _02C6
cmp byte ptr [si],0Dh _IF <cmp byte ptr [si],0Dh>,e
jne _02C3
cmp dx,5E7h _CONTINUE <cmp dx,5E7h>,e
je _0296
mov byte ptr [si],0 mov byte ptr [si],0
jmp short _02C6 _BREAK
_02C3: _ENDIF
inc dx inc dx
jmp short _0296 _ENDW
_02C6:
;;非结构化改造为结构化 ;初步结构化
_057E: _REPEAT
cmp byte ptr [di],0 cmp byte ptr [di],0 ;;非结构化
je _059B je _059B ;;语句
;... ;...
inc di inc di
jmp short _057E _ENDW
_0590: _REPEAT
;... ;...
jmp short _0590 _ENDW
_059B: _059B:
;结构化方法1:重复判断 ;结构化方法2:增设标志
_REPEAT _REPEAT
_BREAK <cmp byte ptr [di],0>,e _IF <cmp byte ptr [di],0>,e
mov $_flag,-1
_ELSE
mov $_flag,0
;... ;...
inc di inc di
_ENDIF
_ENDW _ENDW
_IF <cmp byte ptr [di],0>,ne _IF <cmp $_flag,0>,e
_REPEAT _REPEAT
;... ;...
_ENDW _ENDW
_ENDIF _ENDIF
;;FOR型循环的模拟(有确定的初值,终值,步长)
mov bx,start ;初值(赋值方法多样,甚至不明显出现)
_REPEAT
_BREAK <cmp bx,stop>,g ;终值\
;... ; \
;... ;循环体-->三种语句的相对位置非常灵活
;... ; /
add bx,step ;步长/
_ENDW
=============
注:附件内sitmac.txt、sitmac.inc、sitdial.asm分别是说明文件、宏定义文件、应用实例(对话框窗口)。
[ Last edited by 本是 on 2007-3-5 at 04:02 AM ]
附件
1: Sitmac.rar (2007-3-5 04:02, 10.74 K, 下载附件所需积分 1 点
,下载次数: 20)
|
my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2007-3-5 03:49 |
|
|
happyman06
初级用户
积分 52
发帖 19
注册 2006-9-2
状态 离线
|
『第
2 楼』:
超级经典! 一定要加分! 严重支持 本是大哥!
|
|
2007-3-5 12:19 |
|
|
本是
银牌会员
积分 2201
发帖 789
注册 2005-1-27
状态 离线
|
『第
3 楼』:
1楼修正错误:
;以UNTILCX回跳
mov si,[0081h] mov si,[0081h]
jcxz _027B _IF ,ncxz
_0270: .REPEAT
;... ;...
inc si inc si
loop _0270 .UNTILCX
_027B: _ENDIF
红色标出的行首的.就改为_!
|
my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2007-3-5 13:25 |
|
|
netwinxp
高级用户
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第
4 楼』:
MASM6.1及以上版本本身就支持:
1).IF——.ELSE——.ENDIF
2).WHILE——.ENDW
3).WHILE——.BREAK——.ENDW
4).REPEAT——.UNTIL
这些结构化语句
当子程序用 子程序名 PROTO FAR C 参数1[,参数2....]声明时,用INVOKE调用为C语言风格参数传递;子程序名 PROTO FAR PASCAL 参数1[,参数2....]声明,用INVOKE调用为PASCAL语言风格参数传递。
|
|
2007-7-26 00:43 |
|
|
不点
银牌会员
不甘寂寞的人
积分 2491
发帖 1115
注册 2003-9-24
状态 离线
|
『第
5 楼』:
我很支持本是的做法。我记得 smart boot manager 里面的 nasm 汇编,其中的一些模块就是以结构化的方式来实现的。因此,汇编语言结构化的工作在很早就开展了。不过我认为,这块工作还没有结束,没有达到成熟,因此仍然需要编程语言设计者继续工作。
我希望本是兄做以下两个工作(这也是我想做的,但精力不够只好放弃):
1. 开发一个开放源码的 MS-DOS 替代品。
2. 开发一个编程语言,这个编程语言具有汇编语言的全部功能,又能像 c,c++,以及 UNIX 的 shell 那样。也就是说,从低级到高级再到超高级,都融合在一起了,而且既可以解释执行,也可以编译执行。
|
因为我们亲手创建,这个世界更加美丽。 |
|
2007-7-26 09:03 |
|
|