用.NET&Java的眼光看汇编语言
假设在.NET平台下要实现像下面这张图的效果,我们可以很简单地用几行代码来实现:
预设10个状态值作为“跑马灯”每一张图片的输入值,加上一个Timer控件设定一个Interval值,在Elapased事件下写输出值的代码并刷新UI。当然,前提是有像8255单片机这样的模拟机与程序通信。
但在汇编下要实现这样的效果可真要费一番功夫。先说一下题目要求:
当开关K1 合上其余断开时,L1~L8从右到左逐个点亮直到开关状态改变
当开关K1、K2 合上其余断开时,L1~L8从右到左成对逐次点亮直到开关状态改变
当开关K1、K2、K3合上其余断开时,L1~L8从右到左以3个为一组逐次点亮直到开关状态改变
……
开关K1~K8全部合上时停止
这里需要注意的是每种状态下点亮灯的个数,左移的效果可以用ROL指令来现实,过程中还要保存左移后的值,还有当运行时改变开关状态(2个灯增加到3个灯)时灯的效果也要随着改变。
那天计算机硬件实验花了我一下午才把这个搞出来,后来才发现运行时改变开关状态的这个功能有错误,直接把CL的值赋给了AL,又把新开关状态的值给覆盖了。可惜,下课了,没来得及改…
还有,是否有一款模拟8255或其它单片机的软件,以后直接在寝室里做实验得了,实验室可以不去了
------------------------------------------
有时候在想,汇编这么复杂,指令多(难记,不像高级语言的int、string类型好记)、寄存器限制(8b、16、32b)、IP指针常变(POP、PUSH)、现场保护…真多,这些问题不得不关注
大家知道JIT编译器是把中间语言编译成相应处理器指令,而中间语言(*.dll---.NET、*.class---Java)一般有10几K上百K,写个汇编程序一般不到5K,从大小层面上看JIT编译器应该复杂多了。而且用高级语言编写的程序在运行时都不只调用一个*.dll文件,数量上又增加了一个复杂度。况且高级语言对代码安全、堆栈保护、防止缓冲区溢出都有相当高的要求!
能写出像.NET平台这样的JIT确实是个牛人!
附:做该汇编实验时的代码,有兴趣的可以瞧瞧,在这不做技术讨论
DATA SEGMENT
CTRL DB 82H ;定义控制字
DATA ENDS
CODE SEGMENT
MAIN PROC FAR
ASSUME CS:CODE,DS:DATA
START;
PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV DX,20BH ;8255的控制口地址
MOV AL,CTRL
OUT DX,AL
MOV DX,209H ;8255-B口地址,接收开关输入信号
IN AL,DX
MOV DX,20AH ;8255-C口地址,输出AL值
OUT DX,AL
MOV BL,AL ;保存开关输入信号,BL为左AL左移后的值
MOV CL,AL ;CL为执行L1前AL的值
L1:
MOV DX,209H
IN AL,DX
CMP AL,01H ;逐个与01H、03H…比较
JZ L2
CMP AL,03H
JZ L2
CMP AL,07H
JZ L2
CMP AL,0FH
JZ L2
CMP AL,1FH
JZ L2
CMP AL,3FH
JZ L2
CMP AL,7FH
JZ L2
CMP AL,0FFH
END1:RET ;当输入为0FFH(1111 1111B)或其它值时退出
L2: ;控制二极管循环点亮
MOV AL,BL ;把上次左移后的AL值(存放在BL)送到AL
ROL AL,1 ;左移AL 1位
MOV DX,20AH
OUT DX,AL ;输出移位后的值,效果就是二极管向左点亮了
MOV BL,AL
MOV AL,CL
PUSH BX ;把BX、CX值压栈,保存BL、CL的值
PUSH CX
MOV BX,0FFFFH ;外循环次数
LO: ;外循环
MOV CX,0FFFFH
LI: ;内循环
NOP
NOP
NOP
LOOP LI
SUB BX,1
JNZ LO
POP CX ;弹出CX值
POP BX ;弹出BX值
JMP L1
RET
MAIN ENDP
CODE ENDS
END START