标题: 汇编语言
[打印本页]
作者: zzz19760225
时间: 2016-6-25 20:03
标题: 汇编语言
按照需求引导循环周期节奏的考虑,
寻找可知可见的事,目标,目的,方向,路等。
对数字二进制和多进制的操作
对字符的操作
对自由字符自由的操作
一个肯定的过去现在工具,到一个现在未来的路。
那个装可以溶解一切液体的容器。
一个知错改错,追求更好的现在自我。
每一天都成为第二天的路径台阶平面(哪怕目的是否定昨天和今天自身)。
如何用汇编显示一个自定义的字符
汇编语言这本书的汇编语言论坛
http://www.asmedu.net/bbs/forum.jsp
CSDN > CSDN论坛 > 其他开发语言 > 汇编语言
http://bbs.csdn.net/forums/ASM/
Last edited by zzz19760225 on 2017-11-29 at 16:59 ]
作者: zzz19760225
时间: 2016-6-26 18:28
作者: zzz19760225
时间: 2016-6-26 18:30
http://www.menuetos.net/
MenuetOS 编辑
本词条缺少名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!
MenuetOS是英国软件工程师Ville Mikael Turjanmaa和Madis Kalme开发的,完全由x86汇编语言于2000年写成的一款开放源码的32位操作系统。
中文名 MenuetOS 时 间 2000年 性 质 操作系统
目录
1 简介
2 主要功能
简介编辑
MenuetOS 是英国软件工程师Ville Mikael Turjanmaa和Madis Kalme开发的,完全由x86汇编语言于2000年写成的一款开放源码的32位操作系统。最新的版本为MenuetOS 0.85 (32位)和MenuetOS 0.98.27(64位),可以从其官方网站下载。由于全部使用汇编语言,MenuetOS虽然仅在软盘上使用,仍有非常完整的功能 。
主要功能编辑
MenuetOS0.77汉语版
MenuetOS是一款为个人计算机开发的操作系统,完全由32/64位汇编语言编写。Menuet64在遵循License许可下发布,Menuet32在GPL下开放。Menuet支持32/64位x86汇编程序,为了编写更小,更快的应用,并且有更少的资源占用率。
Menuet没有扎根于UNIX或POSIX标准,也没有基于任何操作系统,其设计目的在于:一开始不添加OS各个不同部分之间额外的层,这些层通常复杂而且平添缺陷。当然,它的汇编特性,也同样相当独特。版本0.98.27 主要是一个漏洞修复发行。
自从头文件能被特定的任何其他语言产生,Menuet的应用结构就不再专门留给汇编语言编程。然而,全部的应用程序设计都是为了运用简单的32/64位汇编。
伴随汇编语言,Menuet那反应敏捷的GUI是易于掌控的。
MenuetOS 1.0 正式版终于发布了,更新内容包括:
Mediaplayer demo, dibcom 0700 TV-tuner firmware
3DS Viewer update from Maciej Guba,
macgub3@wp.pl
Midiplayer, FTP client and server, Draw updates
Https, Chess, C5, Tetris updates
这是一个完全使用汇编语言编写的操作系统。因此它运行起来超快,体积也非常小,它甚至可以放在一张软盘内。MenuetOS提供了抢占式多任务处理,一个引人注目的漂亮GUI,用于网络接入 的 TCP/IP堆栈等等。更令人称奇的是它还能运行Quake游戏,新操作系统当前仍然处于开发阶段。MenuetOS的两位开发者Ville Turjanmaa和Madis Kalme接受PC World Australia的采访,谈论了是什么激励他们去着手去做这样一个令人畏惧的任务,以及操作系统的现状和未来。
Ville称开发操作系统的最初源由是:某日他上网浏览,打开了一个包含脚本语言的网页,然而短短的一段脚本却执行起来无比缓慢,他决定寻找极端的 方法,尽可能多的用汇编语言.....MenuetOS的32位版本采用GPL发布,但64位版本没有使用开源许可证,个人或教育使用则是免费的。开发者 还没有制定1.0版的发布时间表,他们还需要加入新驱动程序和改进现有应用,增加新特性。
Last edited by zzz19760225 on 2016-7-20 at 08:12 ]
作者: zzz19760225
时间: 2016-6-26 18:30
动词和静词,动词运动起来,静词地址保存起来,结构词顺序结构。
动词命令。
送 3 到 西安市火车站街路200号,带 2 从 大连市街路222号
这个动静之间的关系结构,应该有完整的语言模式就是结构词。
命令中心 命令 :从- 加工场开始; 送- 3 到-西安市火车站街路200号; 保存。
地址用工作,身体,居住,书房,表达,工作的仓库,办公室,加工厂;身体的嘴,胃,肠,血管,心脏,屁股;居住的地面,桌子,橱柜;书房的书架,书本,眼睛,脑子,思想空间。
针对机器语言和汉字运算尝试模式的小组,快速应该是基本的,信息的量得是有限有效不会产生或避免误差和循环结构。单向的,类似一个人对另一个人的方向挥舞着不同的字牌,但是没有任何反馈,并且是无连续记忆的,只有这一刻存在,保证准确。
Last edited by zzz19760225 on 2016-9-18 at 21:28 ]
作者: zzz19760225
时间: 2016-6-26 18:31
汇编语言
(面向机器的程序设计语言)
本词条由“科普中国”百科科学词条编写与应用工作项目 审核 。
汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数的地址。在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。普遍地说,特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。
许多汇编程序为程序开发、汇编控制、辅助调试提供了额外的支持机制。有的汇编语言编程工具经常会提供宏,它们也被称为宏汇编器。
汇编语言不像其他大多数的程序设计语言一样被广泛用于程序设计。在今天的实际应用中,它通常被应用在底层,硬件操作和高要求的程序优化的场合。驱动程序、嵌入式操作系统和实时运行程序都需要汇编语言。
中文名
汇编语言
外文名
Assembly Language
学 科
软件工程
产生年代
20世纪50年代
编译方式
汇编
目录
1 发展历程
2 语言特点
▪ 总体特点
▪ 优点
▪ 缺点
3 语言组成
▪ 数据传送指令
▪ 整数和逻辑运算指令
▪ 移位指令
▪ 位操作指令
▪ 条件设置指令
▪ 控制转移指令
▪ 串操作指令
▪ 输入输出指令
4 相关技术
▪ 汇编器
▪ 编译环境
5 发展前景
6 实际应用
7 经典教材
▪ x86处理器
▪ ARM及单片机
发展历程
说到汇编语言的产生,首先要讲一下机器语言。机器语言是机器指令的集合。机器指令展开来讲就是一台机器可以正确执行的命令。电子计算机的机器指令是一列二进制数字。计算机将之转变为一列高低电平,以使计算机的电子器件受到驱动,进行运算。
上面所说的计算机指的是可以执行机器指令,进行运算的机器。这是早期计算机的概念。在我们常用的PC机中,有一个芯片来完成上面所说的计算机的功能。这个芯片就是我们常说的CPU(Central Processing Unit,中央处理单元)。每一种微处理器,由于硬件设计和内部结构的不同,就需要用不同的电平脉冲来控制,使它工作。所以每一种微处理器都有自己的机器指令集,也就是机器语言。
早期的程序设计均使用机器语言。程序员们将用0, 1数字编成的程序代码打在纸带或卡片上,1打孔,0不打孔,再将程序通过纸带机或卡片机输入计算机,进行运算。这样的机器语言由纯粹的0和1构成,十分复杂,不方便阅读和修改,也容易产生错误。程序员们很快就发现了使用机器语言带来的麻烦,它们难于辨别和记忆,给整个产业的发展带来了障碍,于是汇编语言产生了。
汇编语言的主体是汇编指令。汇编指令和机器指令的差别在于指令的表示方法上。汇编指令是机器指令便于记忆的书写格式。
操作:寄存器BX的内容送到AX中
1000100111011000 机器指令
mov ax,bx 汇编指令
此后,程序员们就用汇编指令编写源程序。可是,计算机能读懂的只有
工作过程 工作过程
机器指令,那么如何让计算机执行程序员用汇编指令编写的程序呢?这时,就需要有一个能够将汇编指令转换成机器指令的翻译程序,这样的程序我们称其为编译器。程序员用汇编语言写出源程序,再用汇编编译器将其编译为机器码,由计算机最终执行。
语言特点
汇编语言是直接面向处理器(Processor)的程序设计语言。处理器是在指令的控制下工作的,处理器可以识别的每一条指令称为机器指令。每一种处理器都有自己可以识别的一整套指令,称为指令集。处理器执行指令时,根据不同的指令采取不同的动作,完成不同的功能,既可以改变自己内部的工作状态,也能控制其它外围电路的工作状态。
汇编语言的另一个特点就是它所操作的对象不是具体的数据,而是寄存器或者存储器,也就是说它是直接和寄存器和存储器打交道,这也是为什么汇编语言的执行速度要比其它语言快,但同时这也使编程更加复杂,因为既然数据是存放在寄存器或存储器中,那么必然就存在着寻址方式,也就是用什么方法找到所需要的数据。例如上面的例子,我们就不能像高级语言一样直接使用数据,而是先要从相应的寄存器AX、BX 中把数据取出。这也就增加了编程的复杂性,因为在高级语言中寻址这部分工作是由编译系统来完成的,而在汇编语言中是由程序员自己来完成的,这无异增加了编程的复杂程度和程序的可读性。
再者,汇编语言指令是机器指令的一种符号表示,而不同类型的CPU 有不同的机器指令系统,也就有不同的汇编语言,所以,汇编语言程序与机器有着密切的关系。所以,除了同系列、不同型号CPU 之间的汇编语言程序有一定程度的可移植性之外,其它不同类型(如:小型机和微机等)CPU 之间的汇编语言程序是无法移植的,也就是说,汇编语言程序的通用性和可移植性要比高级语言程序低。
正因为汇编语言有“与机器相关性”的特性,程序员用汇编语言编写程序时,可充分对机器内部的各种资源进行合理的安排,让它们始终处于最佳的使用状态。这样编写出来的程序执行代码短、执行速度快。汇编语言是各种编程语言中与硬件关系最密切、最直接的一种,在时间和空间的效率上也最高的一种,它是高等院校计算机应用技术必修的专业课程之一,对于训练学生掌握程序设计技术,熟悉上机操作和程序调试技术有重要作用
总体特点
1.机器相关性
这是一种面向机器的低级语言,通常是为特定的计算机或系列计算机专门设计的。因为是机器指令的符号化表示,故不同的机器就有不同的汇编语言。使用汇编语言能面向机器并较好地发挥机器的特性,得到质量较高的程序。
2.高速度和高效率
汇编语言保持了机器语言的优点,具有直接和简捷的特点,可有效地访问、控制计算机的各种硬件设备,如磁盘、存储器、CPU、I/O端口等,且占用内存少,执行速度快,是高效的程序设计语言。
3.编写和调试的复杂性
由于是直接控制硬件,且简单的任务也需要很多汇编语言语句,因此在进行程序设计时必须面面俱到,需要考虑到一切可能的问题,合理调配和使用各种软、硬件资源。这样,就不可避免地加重了程序员的负担。与此相同,在程序调试时,一旦程序的运行出了问题,就很难发现。
优点
1、因为用汇编语言设计的程序最终被转换成机器指令,故能够保持机器语言的一致性,直接、简捷,并能像机器指令一样访问、控制计算机的各种硬件设备,如磁盘、存储器、CPU、I/O端口等。使用汇编语言,可以访问所有能够被访问的软、硬件资源。
2、目标代码简短,占用内存少,执行速度快,是高效的程序设计语言,经常与高级语言配合使用,以改善程序的执行速度和效率,弥补高级语言在硬件控制方面的不足,应用十分广泛。
缺点
1、汇编语言是面向机器的,处于整个计算机语言层次结构的底层,故被视为一种低级语言,通常是为特定的计算机或系列计算机专门设计的。不同的处理器有不同的汇编语言语法和编译器,编译的程序无法在不同的处理器上执行,缺乏可移植性;
2、难于从汇编语言代码上理解程序设计意图,可维护性差,即使是完成简单的工作也需要大量的汇编语言代码,很容易产生bug,难于调试;
3、使用汇编语言必须对某种处理器非常了解,而且只能针对特定的体系结构和处理器进行优化,开发效率很低,周期长且单调。
语言组成
数据传送指令
这部分指令包括通用数据传送指令MOV、条件传送指令CMOVcc、堆栈操作指令PUSH/PUSHA/PUSHAD/POP/POPA/POPAD、交换指令XCHG/XLAT/BSWAP、地址或段描述符选择子传送指令LEA/LDS/LES/LFS/LGS/LSS等。注意,CMOVcc不是一条具体的指令,而是一个指令簇,包括大量的指令,用于根据EFLAGS寄存器的某些位状态来决定是否执行指定的传送操作。
整数和逻辑运算指令
这部分指令用于执行算术和逻辑运算,包括加法指令ADD/ADC、减法指令SUB/SBB、加一指令INC、减一指令DEC、比较操作指令CMP、乘法指令MUL/IMUL、除法指令DIV/IDIV、符号扩展指令CBW/CWDE/CDQE、十进制调整指令DAA/DAS/AAA/AAS、逻辑运算指令NOT/AND/OR/XOR/TEST等。
移位指令
这部分指令用于将寄存器或内存操作数移动指定的次数。包括逻辑左移指令SHL、逻辑右移指令SHR、算术左移指令SAL、算术右移指令SAR、循环左移指令ROL、循环右移指令ROR等。
位操作指令
这部分指令包括位测试指令BT、位测试并置位指令BTS、位测试并复位指令BTR、位测试并取反指令BTC、位向前扫描指令BSF、位向后扫描指令BSR等。
条件设置指令
这不是一条具体的指令,而是一个指令簇,包括大约30条指令,用于根据EFLAGS寄存器的某些位状态来设置一个8位的寄存器或者内存操作数。比如SETE/SETNE/SETGE等等。
控制转移指令
这部分包括无条件转移指令JMP、条件转移指令Jcc/JCXZ、循环指令LOOP/LOOPE/LOOPNE、过程调用指令CALL、子过程返回指令RET、中断指令INTn、INT3、INTO、IRET等。注意,Jcc是一个指令簇,包含了很多指令,用于根据EFLAGS寄存器的某些位状态来决定是否转移;INT n是软中断指令,n可以是0到255之间的数,用于指示中断向量号。
串操作指令
这部分指令用于对数据串进行操作,包括串传送指令MOVS、串比较指令CMPS、串扫描指令SCANS、串加载指令LODS、串保存指令STOS,这些指令可以有选择地使用REP/REPE/REPZ/REPNE和REPNZ的前缀以连续操作。
输入输出指令
这部分指令用于同外围设备交换数据,包括端口输入指令IN/INS、端口输出指令OUT/OUTS。
高级语言辅助指令
这部分指令为高级语言的编译器提供方便,包括创建栈帧的指令ENTER和释放栈帧的指令LEAVE。
控制和特权指令
这部分包括无操作指令NOP、停机指令HLT、等待指令WAIT/MWAIT、换码指令ESC、总线封锁指令LOCK、内存范围检查指令BOUND、全局描述符表操作指令LGDT/SGDT、中断描述符表操作指令LIDT/SIDT、局部描述符表操作指令LLDT/SLDT、描述符段界限值加载指令LSR、描述符访问权读取指令LAR、任务寄存器操作指令LTR/STR、请求特权级调整指令ARPL、任务切换标志清零指令CLTS、控制寄存器和调试寄存器数据传送指令MOV、高速缓存控制指令INVD/WBINVD/INVLPG、型号相关寄存器读取和写入指令RDMSR/WRMSR、处理器信息获取指令CPUID、时间戳读取指令RDTSC等。
浮点和多媒体指令
这部分指令用于加速浮点数据的运算,以及用于加速多媒体数据处理的单指令多数据(SIMD及其扩展SSEx)指令。这部分指令数据非常庞大,无法一一列举,请自行参考INTEL手册。
虚拟机扩展指令
这部分指令包括INVEPT/INVVPID/VMCALL/VMCLEAR/VMLAUNCH/VMRESUME/VMPTRLD/VMPTRST/VMREAD/VMWRITE/VMXOFF/VMON等。
相关技术
汇编器
典型的现代汇编器(assembler)建造目标代码,由解译组语指令集的易记码(mnemonics)到操作码(OpCode),并解析符号名称(symbolic names)成为存储器地址以及其它的实体。使用符号参考是汇编器的一个重要特征,它可以节省修改程序后人工转址的乏味耗时计算。基本就是把机器码变成一些字母而已,编译的时候再把输入的指令字母替换成为晦涩难懂机器码。
编译环境
用汇编语言等非机器语言书写好的符号程序称为源程序,汇编语言编译器的作用是将源程序翻译成目标程序。目标程序是机器语言程序,当它被安置在内存的预定位
置上后,就能被计算机的CPU处理和执行。
汇编的调试环境总的来说比较少,也很少有非常好的编译器。编译器的选择依赖于目标处理器的类型和具体的系统平台。一般来说,功能良好的编译器用起来应当非常方便,比如,应当可以自动整理格式、语法高亮显示,集编译、链接和调试为一体,方便实用。
对于广泛使用的个人计算机来说,可以自由选择的汇编语言编译器有MASM、NASM、TASM、GAS、FASM、RADASM等,但大都不具备调试功能。如果是为了学习汇编语言,轻松汇编因为拥有一个完善的集成环境,是一款非常适合初学者的汇编编译器。
发展前景
汇编语言是机器语言的助记符,相对于比枯燥的机器代码易于读写、易于调试和修改,同时优秀的汇编语言设计者经过巧妙的设计,使得汇编语言汇编后的代码比高级语言执行速度更快,占内存空间少等优点,但汇编语言的运行速度和空间占用是针对高级语言并且需要巧妙设计,而且部分高级语言在编译后代码执行效率同样很高,所以此优点慢慢弱化。而且在编写复杂程序时具有明显的局限性,汇编语言依赖于具体的机型,不能通用,也不能在不同机型之间移植。常说汇编语言是低级语言,并不是说汇编语言要被弃之,相反,汇编语言仍然是计算机(或微机)底层设计程序员必须了解的语言,在某些行业与领域,汇编是必不可少的,非它不可适用。只是,现在计算机最大的领域为IT软件,也是我们常说的计算机应用软件编程,在熟练的程序员手里,使用汇编语言编写的程序,运行效率与性能比其它语言写的程序相对提高,但是代价是需要更长的时间来优化,如果对计算机原理及编程基础不扎实,反而增加其开发难度,实在是得不偿失,对比2010年前后的软件开发,已经是市场化的软件行业,加上高级语言的优秀与跨平台,一个公司不可以让一个团队使用汇编语言来编写所有的东西,花上几倍甚至几十倍的时间,不如使用其它语言来完成,只要最终结果不比汇编语言编写的差太多,就能抢先一步完成,这是市场经济下的必然结果。
但是,迄今为止,还没有程序员敢断定汇编语言是不需要学的,同时,汇编语言(Assembly Language)是面向机器的程序设计语言,设计精湛的汇编程序员,部分已经脱离软件开发,挤身于工业电子编程中。对于功能相对小巧但硬件对语言设计要求苛刻的行业,如4位单片机,由于其容量及运算,此行业的电子工程师一般负责从开发设计电路及软件控制,主要开发语言就是汇编,c语言使用只占极少部分,而电子开发工程师是千金难求,在一些工业公司,一个核心的电子工程师比其它任何职员待遇都高,对比起来,一般电子工程师待遇是程序员的十倍以上。这种情况是因为21世纪以来,学习汇编的人虽然也不少,但是真正能学到精通的却不多,它相对于高级语言难学,难用,适用范围小,虽然简单,但是过于灵活,学习过高级语言的人去学习汇编比一开始学汇编的人难得多,但是学过汇编的人学习高级语言却很容易,简从繁易,繁从简难。对于一个全面了解微机原理的程序员,汇编语言是必修语言。
实际应用
随着现代软件系统越来越庞大复杂,大量经过了封装的高级语言如C/C++,Pascal/Object Pascal也应运而生。这些新的语言使得程序员在开发过程中能够更简单,更有效率,使软件开发人员得以应付快速的软件开发的要求。而汇编语言由于其复杂性使得其适用领域逐步减小。但这并不意味着汇编已无用武之地。由于汇编更接近机器语言,能够直接对硬件进行操作,生成的程序与其他的语言相比具有更高的运行速度,占用更小的内存,因此在一些对于时效性要求很高的程序、许多大型程序的核心模块以及工业控制方面大量应用。
此外,虽然有众多编程语言可供选择,但汇编依然是各大学计算机科学类专业学生的必修课,以让学生深入了解计算机的运行原理。
历史上,汇编语言曾经是非常流行的程序设计语言之一。随着软件规模的增长,以及随之而来的对软件开发进度和效率的要求,高级语言逐渐取代了汇编语言。但即便如此,高级语言也不可能完全替代汇编语言的作用。就拿Linux内核来讲,虽然绝大部分代码是用C语言编写的,但仍然不可避免地在某些关键地方使用了汇编代码。由于这部分代码与硬件的关系非常密切,即使是C语言也会显得力不从心,而汇编语言则能够很好扬长避短,最大限度地发挥硬件的性能。
首先,汇编语言的大部分语句直接对应着机器指令,执行速度快,效率高,代码体积小,在那些存储器容量有限,但需要快速和实时响应的场合比较有用,比如仪器仪表和工业控制设备中。
其次,在系统程序的核心部分,以及与系统硬件频繁打交道的部分,可以使用汇编语言。比如操作系统的核心程序段、I/O接口电路的初始化程序、外部设备的低层驱动程序,以及频繁调用的子程序、动态连接库、某些高级绘图程序、视频游戏程序等等。
再次,汇编语言可以用于软件的加密和解密、计算机病毒的分析和防治,以及程序的调试和错误分析等各个方面。
最后,通过学习汇编语言,能够加深对计算机原理和操作系统等课程的理解。通过学习和使用汇编语言,能够感知、体会和理解机器的逻辑功能,向上为理解各种软件系统的原理,打下技术理论基础;向下为掌握硬件系统的原理,打下实践应用基础。
经典教材
汇编语言教材很多,各种处理器都有涉及,粗略统计不下百种。在这么多的教材里,用得较多的可以分类列举如下:
x86处理器
1.《x86汇编语言:从实模式到保护模式》,李忠著,电子工业出版社,2013-1 。
基于INTEL x86处理器、NASM编译器和BOCHS虚拟机。汇编语言就是处理器的语言,从这个意义上来说,既然学习汇编语言,就必须直接面向硬件编程,而不是使用莫名其妙的DOS中断和API调用。这是一本有趣的书,它没有把篇幅花在计算一些枯燥的数学题上。相反,它教你如何直接控制硬件,在不借助于BIOS、DOS、Windows、Linux或者任何其他软件支持的情况下来显示字符、读取硬盘数据、控制其他硬件等。
我们知道,32位和64位是主流,实模式和DOS操作系统已经成为历史,Linux和Windows都工作在保护模式下。这本书从实模式讲到32位保护模式,尤其以32位保护模式为重点,阅读本书,对理解现代计算机和现代操作系统的工作原理有非常大的帮助作用。
2.《汇编语言》(第2版),王爽 著,清华大学出版社,2013-4-1
基于INTEL 8086处理器、MASM编译器,以及DOS平台的汇编教材,完全以8086处理器的实模式为主,不涉及常用的32位和64位模式,但因为通俗易懂,读者反映很好。
3.《80X86汇编语言程序设计教程》,杨季文等 编著,清华大学出版社,1999-3-1
基于INTEL x86处理器、MASM和TASM编译器,包含16位实模式和32位保护模式的内容,而且对后者讲述较为详细。
4.《32位汇编语言程序设计》,钱晓捷 编著,机械工业出版社,2011-8-1
基于INTEL x86处理器、MASM编译器,以及WINDOWS平台的汇编教材。
5.《16/32位微机原理汇编语言及接口技术》,钱晓捷,陈涛编著,机械工业出版社,2005-2-1
基于INTEL x86处理器,论述16位微型计算机的基本原理、汇编语言和接口技术,并引出32位微机系统相关技术。
6.《Intel汇编语言程序设计》(第五版),(美)欧文 著,电子工业出版社,2012-7-1
基于INTEL x86处理器、MASM编译器,以及DOS/WINDOWS平台的汇编教材,既有16位实模式的内容,也有32位保护模式的内容。
7.《汇编语言的编程艺术》(第2版),(美)海德 著,清华大学出版社,2011-12-1
基于INTEL x86处理器,使用了作者自制的高级语言汇编器(High Level Assembler,HLA)作为教学工具,以部分地获得高级语言的优势和功能。
8.《x86 PC汇编语言、设计与接口》(第五版),(美)马兹迪,考西著,电子工业出版社,2011-1-1
基于INTEL x86处理器,既讲了16位实模式的内容,也讲了32位保护模式的内容,对64位也有所介绍。
ARM及单片机
1.《汇编语言程序设计--基于ARM体系结构》(第2版),文全刚等主编,北京航空航天大学出版社,2010-8-1
基于ARM体系结构的处理器,是学习嵌入式技术的入门教材。
2.《零基础学AVR单片机》,徐益民等编著,机械工业出版社,2011-1-1
单片机概述、avr单片机的开发工具、avr单片机c语言、atmega16单片机基本结构、avr的指令系统与汇编系统等。
3.《基于Multisim10的51单片机仿真实战教程》,聂典,丁伟主编,电子工业出版社,2010-2-1
阐述了NI Multisim 10在单片机仿真中的各项主要功能。
4.《PIC18微控制器:体系结构、编程与接口设计》,(美)贝里著,清华大学出版社,2009-4-1
微控制器广泛应用于汽车、家电、工业控制、医疗设备等众多领域。本书以Microchip公司的PIC18系列微控制器为例,全面讲解如何使用C语言和汇编语言对微控制器进行编程。
5.《CASL汇编语言程序设计》,赵立辉编著,中国电力出版社,2002-10-1
CASL汇编语言是中国计算机软件专业技术资格和水平考试高级程序员级的必考内容。本书是讲述CASL汇编语言程序设计的专著。
-----------------------------------------------------------------------
http://vdisk.weibo.com/s/BJ8eVgUUujf2u
Last edited by zzz19760225 on 2017-11-11 at 19:03 ]
作者: zzz19760225
时间: 2016-6-26 18:32
1
作者: zzz19760225
时间: 2016-6-26 18:33
1
作者: zzz19760225
时间: 2016-6-26 18:35
1
作者: zzz19760225
时间: 2016-6-26 18:36
1
作者: zzz19760225
时间: 2016-6-26 18:37
1
作者: zzz19760225
时间: 2016-6-26 18:38
1
作者: zzz19760225
时间: 2016-6-26 18:39
1
作者: zzz19760225
时间: 2016-6-26 18:40
1
MASM
1
简单传输指令 13
1 |---MOV
2 |---MOVSX
3 |---MOVZX
4 |---PUSH
5 |---POP
6 |---POPF
7 |---XLAT
8 |---XCHG
9 |---SAHF
10|---LDS
11|---LEA
12|---LES
13|---LAHF
2
算术运算指令 19
1 |---AAD
2 |---ADD
3 |---AAS
4 |---AAM
5 |---ADC
6 |---AAA
7 |---SUB
8 |---SBB
9 |---MUL
10|---IMUL
11|---CBW
12|---CMP
13|---CWD
14|---DAA
15|---DEC
16|---DIV
17|---IDIV
18|---INC
19|---NEG
3
逻辑运算指令 13
1 |---AND
2 |---OR
3 |---XOR
4 |---NOT
5 |---TEST
6 |---SHL
7 |---SHR
8 |---SAL
9 |---SAR
10|---ROL
11|---ROR
12|---RCL
13|---RCR
4
串操作指令 16
1 |---MOVS
2 |---MOVSB
3 |---MOVSW
4 |---CMPS
5 |---CMPSB
6 |---CMPSW
7 |---SCAS
8 |---SCASB
9 |---SCASW
10|---STOS
11|---LODS
12|---REP
13|---REPZ
14|---REPE
15|---REPNZ
16|---REPNE
5
程序转移指令 55
1 |---JMP
2 |---JC
3 |---JNC
4 |---JE
5 |---JZ
6 |---JNE
7 |---JNZ
8 |---JS
9 |---JNS
10|---JO
11|---JNO
12|---JP
13|---JPE
14|---JNP
15|---JPO
16|---JA
17|---JNBE
18|---JAE
19|---JNB
20|---JB
21|---JNAE
22|---JBE
23|---JNA
24|---JG
25|---JNLE
26|---JGE
27|---JNL
28|---JL
29|---JNGE
30|---JLE
31|---JNG
32|---LOOP
33|---LOOPZ
34|---LOOPE
35|---LOOPNZ
36|---LOOPNE
37|---CALL
38|---RET
39|---IRET
40|---IN
41|---OUT
42|---INT
43|---INTO
44|---CLC
45|---CLD
46|---CLI
47|---CMC
48|---ESC
49|---HLT
50|---LOCK
51|---NOP
52|---STC
53|---STD
54|---STI
55|---WAIT
6
汇编伪指令 3
1 |---EQU
2 |---DB
3 |---SEGMENT
Last edited by zzz19760225 on 2018-1-1 at 08:06 ]
作者: zzz19760225
时间: 2016-6-26 18:40
标题: 二进制组合可能范围的编码化,伪二进制的十进制
作者: zzz19760225
时间: 2016-6-26 18:43
汇编程序一般采用二次扫描完成对___源程序___的汇编任务.
第一遍扫描主要完成______________的建立;
第二遍扫描将每个程序行转换为____________或________________,从而生成___________.
同时还可以根据需要生成__________________文件和__________________文件.
两次扫描都可以遇到______END__________指令而结束.
spasm
no file specified 没有指定文件
Last edited by zzz19760225 on 2017-11-29 at 13:01 ]
作者: zzz19760225
时间: 2016-6-26 18:43
标题: debug
debug命令 免费编辑 添加义项名
B 添加义项 ?
所属类别 : 其他
DEBUG是一个DOS实用程序,是供程序员使用的程序调试工具,可以用它检查内存中任何地方的字节以及修改任何地方的字节。它可以用于逐指令执行某个程序以验证程序运行的正确性,也可以追踪执行过程、比较一个指令执行前后的值以及比较与移动内存中数据的范围,读写文件与磁盘扇区。
词条 百科 精彩信息一览无遗
基本信息
中文名称
debug命令
性质
DOS实用程序
作用
供程序员使用的程序调试工具
优点
检查内存字节
目录
1命令介绍
2命令功能
3实际应用
折叠编辑本段命令介绍
它的功能包括以下几个方面。
⒈ 直接输入,更改,跟踪,运行汇编语言源程序;
⒉ 观察操作系统的内容;3.查看ROM BIOS的内容;
⒋观察更改RAM内部的设置值;
⒌以扇区或文件的方式读写软盘数据
DEBUG把所有数据都作为字节序列处理。因此它可以读任何类型的文件。DEBUG可以识别两种数据: 十六进制数据和ASCⅡ码字符。它的显示格式是各个字节的十六进制值以及值在32与126之间的字节的相应ASCⅡ码字符。
在DEBUG中输入数据有两种方法: 提示方法和非提示方法。在用提示方法时,用户可以输入要求输入数据的命令,后跟数据所要输入的地址。然后用户就可以看到该地址中已有内容及一个冒号提示符。此时用户可以在提示符下输入一个新的值或者按下回车键或CTRL+C回到短横(-)提示符。在运用非提示方法时,用户可以输入要输入数据的内存地址以及要输入的字节。但与使用字处理程序或正文编辑程序时不一样,在使用DEBUG时,用户不能直接移动光标到一入口点输入或修改数据,而要一次输入一个或几个字节。
在使用DEBUG时可以只涉及内存中的数据,从而一般都要指定所要处理的内存地址,地址的输入格式是: : 。如果没有输入地址,DEBUG将假定为当前内存段,从位于地址100H的字节开始。前100H字节保留给程序段前缀使用,这一专用区域用于建立DOS与程序之间的联系。DEBUG总是用四位十六进制数表示地址。用两位数表示十六进制数据。
讲到这里大家应该对DEBUG有了初步的了解,但是光知道这些可不够,接下来我来讲讲DEBUG的命令格式和命令。当输入
DEBUG
调用了DEBUG程序,就会出现一个短横提示符,用户就可以在这一短横后输入DEBUG程序的命令。有些DEBUG命令会显示一个内存地址并产生一个作为提示符的冒号。在这些提示符后,用户可以输入一个新值以改变所显示位置原来的值。如果用户不输入一个新值而是按下回车或CTRL+C,那么原来的值不会改变。
一般用不着把地址和命令名字分开。例如,用转储命令D察看100号地址的数据,那么这个命令可以用以下任一种形式输入:
D100
D,100
D 100
如果输入的命令中出现了错误,DEBUG将在下一行对着错误的位置标记出来,例如:
-s100 d 12
^Error
折叠编辑本段命令功能
折叠A汇编命令
功能: 将指令直接汇编成机器码输入到内存中。
说明: 用于小段程序的汇编及修改目标程序,所有输入的数字均采用十六进制, 用户装入内存的汇编语句是连续存放的,若没有指定地址,并且前面没有使用汇编命令,该语句被汇编到 CS:0100区域。
例A:>DEBUG
-a 0100
08F1:0100 MOV AH,09
08F1:0102 MOV DX,109
08F1:0105 INT 21H;
08F1:0107 INT 21H;<-XP下运行cmd debug时,应该是INT 20H,21H会出遇无效指令错误
08F1:0109 db 'May I help you $'
08F1:0115←离开a状态
-g ←运行
May I help you 运行结果
Program terminated normally表示运行正常
折叠C比较命令
功能: 比较两内存区域中的内容是否相同,若不同则显示其地址和内容。
如:C4000:0 3F 100
就是用来比较4000:0000-4000:003F与DS:0100-DS:013F之间的内容:其显示格式如下:
内存地址1内含值1内含值2内存地址2
例:比较4000:0 3F 100内容的差异
-C4000:0 3F 100
4000:0000 64 43 08F1:0100
4000:0001 3E 69 08F1:0101 显示内容的差异处
4000:0002 78 FF 08F1:0102
……………………………………
如果要比较的范围在DS内,则段地址不必指出:
如:-C 0 4 100;比较DS:0---DS:4与DS:100---DS:104
C命令的另一种格式如下:C地址1 L 长度 地址2
如:-C000:0 L4 0;由0000:0与与DS:0开始比较它同-C0000:0 3 0命令相等,显示结果如下:
0000:0000 8A C0 08F1:0000
0000:0001 10 20 08F1:0001 它们都比较4个字节
0000:0002 1C 00 08F1:0002
0000:0003 49 7F 08F1:0003
折叠转储命令
* D 或D 转储命令
功能: 以内存映象方式显示内存中的信息。
说明: 转储用左右两部分显示内存映象内容,左边以十六进制,右边以ASCⅡ字符显示,所有不可打印字符用句号(。)表示。每行显示16个字节的内容,在第八和第九个字节之间有一个连字符 - 此命令隐含的段地址为DS的值。若未指定起始地址,则D命令从显示的最后一个单元的下一个单元开始显示,若以前没有使用给D命令, 则从初使化的段寄存器的内容,加上地址偏移量 0100H 开始显示。
例:-d10,4f即为显示DS:4f的内容在D命令中如不指出段地址,则其默认为DS段。
如指明段地址,则从指明的段地址列出指定的范围
如:-dfff:00:0f
我们也可以指定长度来列出所需要内存内容
如:-d 100 L20即为显示由DS:100-DS:11F的内容,共20H个字节:
* E
⑴用给定内容代替指定范围的单元内容
-E地址 内容表
例:-E100 41 42 43 44 48 47 46 45
-D 100,L08
08F1:0100 41 42 43 44 48 47 46 45 ABCDHGFE…
⑵逐个内存内容
例:-E 100:
08F1:0100 76 42 :42是操作员键入
此命令是将原100号内存内容76修改为42,用D命令可察看。
* F 填写命令
功能: 将要填写的字节或字节串填入由地址范围指定的存储器中。
例:-f100 120 61 62 63 64
-d100 11f
08F1:0100 61 62 63 64 61 62 63 64 -61 62 63 64 61 62 63 abcd abcd abcd abcd
08F1:0110 13 67 98 E3 C8 2E B3 B6 -03 21 AC 19 3121 4E 96 g……1…
如果数据行超出指定的范围,则填不下的数值会被忽略。
例:-f 100 107 41 43 43 44 45 46 47 48 49 4A 4B 4C 4D -d 100,lof
08F1:0100 41 42 43 44 45 46 47 64 -61 62 63 64 ABCDEFGdabcdabcd
由上例可看出,超出范围的数据被忽略
另外,F和E命令都可填入字符串:
如:-F 100 105 "MSDOS"
-d 100 l0f
08F1:0100 4D 53 44 4F 53 46 47 64 -61 62 63 64 MS DOS FGabcd abcd
折叠G执行命令
功能: 执行正在调试的程序,当达到断点时停止执行, 并且显示寄存器标志和下一条要执行的命令。
说明: 如果没有指定起始地址,那么当前指令地址由CS,IP寄存器的内容来决定,如果用户指定起始地址就从指定的起始地址开始执行。如果指定断点,当指令到达指令地址时停止执行,并显示各寄存器标志位的内容和下一条要执行的命令,最多允许用户设定10个断点。
例:A:\>debug tan.exe
-u:反编译成汇编语言程码
…………
. .
-g 100 指定中断点
Program terminated normally:
另外:我们在DEBUG下可运行一个文件.EXE
如:A:\>debug tan.exe
-g
即可开始运行此程序,和在DOS下完全一样:
* H 十六进制算术运算命令
功能: 分别显示两个十六进制数相加的和以及第一个数减去第二个数的差。
说明: 替用户完成简单的十六进制数的运算。
例:-h4538 5623
9B5B EF15
折叠I命令
功能: 从指定的端口输入并显示(用十六进制)的一个字节。
例:-i70
F9;显示70端口的内容为F9
I命令可由80X86的64K个端口取数据
折叠L命令
功能: 将一个文件或盘的绝对扇区装入存储器。
说明: 单个L命令能够装入的最大扇区数是 80H,其中盘号 0,1,2,3……分别代表 A,B,C,……出现读盘错,显示错误信息。
⑴格式1.L装入地址 驱动器名 起始扇区/扇区数
这种方式可把磁盘上指定扇区范围的内容装入到存储器从指定地址开始的区域中,在此外扇区编号引用逻辑/扇区的方式。
例:-L 100 0 01,将A驱的0扇区装至CS:100上
-d 100 10f
08F1:0100 EB 3C 90 3C 53 44 4F 53 -36 2E 32 32 02 01 01 00.L,MSDOS 6.22……
⑵格式2:L装入地址
这种方式可把指定文件装入内存,装入的文件可在进入DEBUG时指定亦可用N命令建立,格式为-n文件名:
例1 DEBUG tan.pas
-L 100
例2 DEBUG
-n tan.pas
-L 100
须知:L命令只能读取逻辑扇区,不能读取硬盘分区表
L命令中所用的磁盘代码A=00,B=01,C=02……
折叠M数据命令
功能: 把地址范围内的存储器单元的内容移到起始地址的指定地址中
说明: 传送期间,源区和目标区可以部分重叠;传送后源区域数据保持不变。
例:-e100 41 42 43 44 45
-d100 10f
08F1:0100 41 42 43 44 45 62 62 63 64 -61 62 63 64 61 62 63 64 ABCDEBCDABCDABCD
-M 100 104 110
-d110 L1F
08F1:0100 41 42 43 45 0A 21 19-20 01 01 20 07 96 87 9F ABCDE……
* N
功能: 定义操作文件名。
说明: 可同时定义两个操作文件,并将形成的文件控制块相应的设置在内存 CS:5C和CS:6C上,供以后的L和W命令操作之用。我们在运行程序侦错时,在启动DEBUG时在其后加文件程序名以及该程序的参数或运行文件,但当我们侦错一段后,可能装入其它文件来测试,这时我们可利用N命令来设置而无需退出DEBUG。
例:A:\>DEBUG tan.exe
-n youg.pas
当程序侦错一段时间后,若要把tan.exe装入tan1.pas则-ntanl.pas
折叠O输出命令
功能: 发送字节到指定的输出端口。
例:当我们遇到开机要求输入口令时,可用如下方式取消
-O 70 10
_O 71 00
折叠P进程命令
功能: 将一个子程序调用指令,循环指令,中断指令或一个重复字符串指令,停止在下一条指令上。
说明: 在执行一条子程序调用指令,循环指令,中断指令或一个重复字符串指令时,发出P命令去执行有关指令,并且返回到要执行的下一条指令。P命令和T一样选用来跟踪程序运行过程用的命令,我们可以在P命令中指定程序运行的起始地址,指令个数,如未指定则CS:IP所指定程序的地址开始一次运行一条令。
P与T命令的差别在于P命令把CALL/INT当成一条指令来执行,简化了跟踪过程,P命令只运行RAM内存的命令,而T命令则可运行RAM和ROM里的程序。
折叠R寄存器命令
功能: 一,显示单个寄存器的内容,并提供修改功能。二,显示所有寄存器内容, 再加上字母标志位状态以及要执行的下一条指令。三,显示8个标志位状态, 并提供修改功能。若不想改变则回车即可。
例:-r bx
bx 0050
:51
-r
AX=0000 BX=0051 CX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0003 ES=0CD3 SS=0CD3 IP=0100 NV UP EI PL NZ NA PO NC
0CD3:0100 0F DB OF
若想改变标志寄存器,用-RF回车,则DEBUG会将标志内容显示出来,若想改变任一标志,只要输入该标志的名称即可。
标志名称 设置 未设置 标志名称 设置 未设置
滋出 OV(溢出) NV(未溢出) 零位 ZR NZ(不等于零)
方向 DN(减少) UP(增加) 辅助进位 AC NA(无进位)
中断 EI(许可) DI(禁止) 奇偶标志 PE(偶) PO(奇)
符号 NG(负) PL(正) 进位 CY NC(清除进位)
例:-Rf
NV UP EI PL NZ NA PO NC :-OV DI← 输入值
折叠S命令
功能: 在指定的地址范围内查找给定的字符串。
说明: 用来指定在地址范围内查找一个字符串,若找到则显示其地址, 否则直接显示DEBUG提示符。隐含地址为DS段值。
在此内存可以用(起始地址)(终止地址)或(起始地址)L(长度)的方式来表示,而字符串与数据行则可混合使用:如:02.76"BC"。
例:-d100 lof
08F1:0100 OF 2A 41 43 0B 31 42 96 -FF F0 B9 8A F3 00 B1.. AC,1B...
-S 100 lof"AC"
08F1:0102← 表示找到,由0102开始,
折叠T跟踪命令
功能: 逐条跟踪程序的执行,每条指令执行后都将显示各寄存器的内容。
说明: 通常采用跟踪一条指令,但用户也可以用指令条数设定一次跟踪多条指令, 每执行一条指令之后,显示所有寄存器的内容和标志状态。
逐条指令跟踪 -T
从指定地址起执行一条指令后停下来,显示所有寄存器内容及标志位的值,如来指定地址则从当前CS:IP开始执行。
A:\>DEBUG
-A
08F1:0100 MOV DL,03H
08F1:0102 MOV AH,02H
08F1:0104 INT 21H
08F1:0106 INT 20H
08F1:0108
-T
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=08F1 ES=08F1 SS=08F1 CS=08F1 1P=0105 NV UP EI PL NZ PO CY
09F1:0102 B402 MOV AH,02
若指定起始地址,则T命令会从指定的地址开始跟踪,我们还可以指定跟踪一次所运行指令的个数,用Ctrl+S暂停屏幕的显示,以便观察。
-t=100 10;由CS:100开始跟踪10条指令
折叠U地址命令
功能: 将内存中的内容转换为汇编语句。
说明: 反汇编的字节数取决与用户的系统显示形式,以及在U命令中使用的可选项。
⑴从指定地址开始编译,反汇编32个字节
-U←从CS:100开始,其反汇编32个字节
如果地址被省略,则从一个U命令的最后一条指令的下一条单元开始汇编32个字节。
⑵对指定的存贮范围进行反汇编
-u起始地址 终止地址(L 长度)
例:-U 100 109
08F1:0100 CD20 INT 20
08F1:0102 FF9F009A CALL FA12
08F1:0106 F0 LOCK
08F1:0107 FE1D CALL FAR
08F1:0109 F0 LOCK
说明:如指定了范围则整个范围全都会被反编译
折叠W写盘命令
* W 写盘命令
功能: 将修改过的数据写到磁盘上。
说明: 可以将指定内存地址开始的数据写在磁盘上,可以在没有指定参数, 或指定地址参数的情况下,将调试文件写在磁盘上。
在运行W时需设置文件的大小CX或BX寄存器
⑴把数据写入磁盘的指定扇区
-W 起始地址 驱动器名 起始扇区 扇区数
⑵把数据写入指定文件中
-W 起始地址
例A:\>DEBUG
-A
08f1:0100....
. 写入程序段
08F1: 012A....
-R CX
CX:0000
:2A←写入字节数,即为程序结尾地址减起始地址
-n tan.com←设置文件名,需后缀为com
-w
Wring 002A bytes
-q
A:\>TAN←即可执行此程序
* "XD"命令:释放EMS内存
例:-XD 0001
handle 0001 deallocatel←释放了
利用XD释放后可再分配
*"XM"命令;把扩充内存上的内存页区映射到主内存区
格式:XM RAM 长页码 主内存页码句柄
例:-XM3 2 0001←把0001号句柄的第3号逻辑页区映射到2号真实页区
Logical page 03 mapped to physical page 02
*"XS"命令:显示当前EMS使用情况。
格式 -XS
折叠编辑本段实际应用
⒈ 非物理0磁道坏软盘的修复
此种损坏从软盘盘面上来看并没有明显的划伤和霉变。一般可以恢复其数据,也可使软盘重新在利用。
处理方法如下:
Ⅰ. 进入debug
Ⅱ. 取一张引导区没有损坏的好磁盘,插入软驱
-l 100 0 0 1
Ⅲ. 插入损坏的磁盘到软驱
-w 100 0 0 1
-q
注意:好盘与坏盘容量必须相同
⒉ 物理0磁道坏软盘中的数据读取
对于0磁道损坏的磁盘,一般来说是应该抛弃了,当你也不妨试一试已下方法:
磁化处理:用较强的磁铁在靠近坏磁盘的表面处反复移动,切不可碰到磁盘介质,以免划伤表面,然后在试试格式化。
软盘换面:小心的将磁盘打开,坚磁片与金属芯片分开,翻面后再按原来的方法粘在一起即可,在重新格式化。
diskfix:对于diskfix想必大家都用的比较多了,里面的磁盘修复功能很好用的。能修复大多数磁盘表面错误。
⒊ 硬盘启动失败处理
在正常机上格式化一张软盘,无其它数据
进入debug
-l 0 2 0 1
-w 0 0 0 1
-q
用系统盘启动故障机后
在进入debug
-l 0 0 0 1
-w 0 2 0 1
-q
⒋ 软盘不能正确读取解决方法
如果使用软盘时出现如下提示
general failure error reading drive a
可以用以下方法解决:
将一张好盘插入软驱
进入debug
-a 100
****:*100 mov al,0
****:**** mov cx,1
****:**** mov dx,0
****:**** mov bx,1000
****:**** int 25
****:**** int 20
回车
-g=0100
插入坏盘并进入debug
-a 200
****:*100 mov al,1
****:**** mov cx,1
****:**** mov dx,0
****:**** mov bx,1000
****:**** int 26
****:**** int 20
回车
-g=200
⒌ cmos 数据的保存,恢复
cmosram的'地址口'的口地址为 70h '数据口'的口地址为 71h 读取时只需将读的cmosram的地址送到70h,随后就可以从71 h中得到所需数据。
⑴读取cmos数据 进入debug
-a 100
****:*100 mov bx,1000
****:**** mov cx,0040
****:**** mov ax,0000
****:0109 mov dx,cx
****:**** mov cx,0005
****:010e loop 010e
****:**** out 70,al
****:**** mov cx,0005
****:0115 loop 0115
****:**** in al,71
****:**** mov 【bx】,al
****:**** cmp ah,0e
****:**** jb 0123
****:**** add ah,80
****:0123 inc ah
****:**** inc bx
****:**** mov cx,dx
****:**** mov al,ah
****:**** loop 0109
****:**** mov ah,3c
****:**** mov dx,0150
****:**** mov cx,0020
****:**** int 21
****:**** mov bx,ax
****:**** mov dx,1000
****:**** mov cx,0040
****:**** mov ah,40
****:**** int 21
****:**** mov ah,4c
****:**** int 21
-a 150
****:0150 db "cmos.dat",0
****:0159
-r cx
cx 0000
:60
-n save cmos.com
-w
-q
-w 100 2 0 1
-q
⑵恢复cmos数据 进入debug
-a 100
****:*100 mov cx,0150
****:**** mov ah,3d
****:**** mov al,00
****:**** int 21
****:**** mov dx,1000
****:**** mov bx,ax
****:**** mov cx,0040
****:**** mov ah,3f
****:**** int 21
****:**** mov ax,0000
****:**** mov bx,dx
****:**** mov dx,cx
****:**** mov cx,0005
****:**** loop 011f
****:**** mov al,ah
****:**** out 70,al
****:**** mov cx,0005
****:**** loop 0128
****:**** mov al,【bx】
****:**** out 71,al
****:**** jb 0136
****:**** add ah,80
****:**** inc ah
****:**** inc bx
****:**** mov cx,dx
****:**** loop 011a
****:**** mov ax,0040
****:**** mov ds,ax
****:**** mov ax,1234
****:**** mov 【0072】,ax
****:**** jmp ffff:0000
-a 150
****:0150 db "cmos.dat",0
****:0159
-r cx
cx 0000
:60
-n write cmos.com
-w
-q
⒍ dos 引导扇区数据的保存与恢复
dos引导程序是被读到内存0000:7c00初开始执行的
获得正常的引导程序
进入debug
-l 100 2 0 1
-n a:dosboot.com
-r cx
:200
-w
-q
装入引导程序
进入debug
-n a:dosboot.com
-l
-r cx
:200
-w 100 2 0 1
-q
⒎ 硬盘主引导扇区数据的保存与恢复
硬盘工作正常时读取主引导扇区信息
注意:当分区改变时不能用此数据恢复
保存主引导扇区数据进入debug
-a 100
mov ax,0201
mov bx,0110
mov cx,0001
mov dx,0080
int 13
int 3
-g=100
-e 102 3
-e 10e c3
-r bx
bx 0110
:0
-r cx
cx 0001
:210
-n a:rboot.com
-w
-q
恢复主引导扇区数据:只需运行a盘的rboot.com
⒏ 硬盘非分配表备份与恢复
计算机运行正常时分配表备份
进入debug
-l 100 2 0 1
-n a:dbrup.dat
-r cx
:200
-w
恢复
进入debug
-n a:dbrup.dat
-l
-w 100 2 0 1
-q
⒐ 硬盘保护卡内幕
对于经常在外边上机的人来说,计算机维护人员一旦设置硬盘保护卡,自己作一些事来特别麻烦,想不想屏蔽掉硬盘保护卡,用以下方法或许可以借鉴:
进入debug
-a 100
mov ah,0
mov dl,0
int 13
-t
一直按t知道找到 cs=f000 记下此时 ds 的值 如:1234
-e e0:4c
34 12 00 f0
-q
⒑ 用debug作硬盘低级格式化
硬盘低级格式化一般用dm,但debug也可以低级格式化硬盘
进入debug
-a 100
mov ax,500
mov bx,180
mov cx,0
mov dx,80
int 13
int 3
-e 180 0 0 0 2
-q
⒒ 冷启动与热启动
用debug实现系统冷启动与热启动程序
冷启动:
-a 100
jmp ffff:0
int 20
-n a:reset.com
-r cx
:0007
-w
-q
热启动:
-a 100
mov ax,0040
mov ds,ax
mov ax,1234
mov si,0072
mov (si),ax
jmp ffff:0
-n a:rset.com
-r cx
:0014
-w
-q
⒓ dos内部命令加密
如加密 dir
用pctools或diskedit找 c:下的command.com文件
编辑该文件
pctools中:f-----f1 然后找所有03 44 49 52 找到后按f5修改成你所要的值 如:foo 以后只有输入foo 才能列出文件或文件目录。
diskfix 有良好的界面,操作起来和pctools差不多。
注意:如果不能修改,则解开文件的锁定 luck
其它命令代码
type 04 54 59 50 45
cd 02 43 44
del 03 44 45 44
copy 04 43 49 50 59
Last edited by zzz19760225 on 2017-11-13 at 14:06 ]
作者: zzz19760225
时间: 2016-6-26 18:44
汇编初学者问题合集 :大熊猫侯佩
http://blog.csdn.net/mydo/article/details/1776304
1 debug中使用sal指令的问题
在debug里面使用A指令,输入如下代码:
***************************
MOV AX,0ABC
DEC AX
AND AX,00FFH
MOV CL,4
SAL AL,1
***************************
当输入到 sal al,1 时提示error
shl 与 sal 作用是完全一样的,所以在编译的时候自动将
sal 转换成了 shl .使用sal dubug 不识别,换成shl就搞定了。
可以把上述代码编译成 EXE 文件,然后用debug 中 u 指令查看,
结果 sal 的地方 被换成 shl。
Last edited by zzz19760225 on 2017-11-29 at 17:34 ]
作者: zzz19760225
时间: 2016-6-26 18:45
【转】debug显示字符串“hello world”,解决某人讲课讲了半天都没让人明白debug怎么用的问题,多看几遍就知道怎么用了
另一种显示在屏幕上字符串的方法
注意:在你输入数据的时候,按"-"键将会可以让你回退一格。
PROMPT> DEBUG<按回车>
-E 200<按回车> (从偏移地址200开始。输入"Hello,World")
48<按空格>65<按空格> (输入48h (H)和65h (e))
6C<按空格>6C<按空格> (输入6Ch (l)和6Ch (l))
6F<按空格>2C<按空格> (输入6Fh (o)和2Ch (,))
57<按空格>6F<按空格> (输入57h (W)和6Fh (o))
72<按空格>6C<按空格> (输入72h (r)和6Ch (l))
64<按空格>24<按空格> (输入64h (d)和24h ($))
<按回车> ("Hello,World" 已经输入完毕)
-D 200<按回车> (显示你刚刚输入的内容:
48 65 6C 6C 6F 2C 57 6F-72 6C 64 24 ... HELLO,WORLD$...)
-A 100<按回车> (用汇编语言写一个新程序在IP-100h处开始)
MOV AH,09<按回车> (选择DOS的09号功能调用,显示字符串)
MOV DX,0200<按回车> (把输出地址(200h),放进寄存器)
INT 21<按回车> (执行DOS功能调用,显示"Hello,World")
INT 20<按回车> (退出程序回到DOS状态)
<按回车> (结束汇编语言输入,回到DEBUG输入状态)
-G<按回车> (从 CS:IP开始运行程序, 就是从107F:0100h开始执行程序)
现在,我们可以把这个程序保存进一硬盘
-D 100<按回车> (纪录:程序的起始点在100h)
-D 200<按回车> (纪录:程序数据单元的结束点是在020Bh)
-H 20B 100<按回车> (运算 20Bh-100h=10Bh;程序长度267字节)
030b 010b (前者是相加运算的结果,后者是相减运算的结果)
-R BX<按回车> (检查BX寄存器的值)
:0000<按回车> (设置BX为0000h,程序的长度是BX:CX,实际上你可以把和CX写到一起,即实际长度为:0000010Bh,这样些的目的是使你可以计算更大的程序的长度)
-R CX<按回车> (设置CX 为010Bh, 这就是这个程序的长度了)
:010B<按回车> (现在你可以把这个108字节的程序写入硬盘了)
-N printhw.com<按回车> (将要写入硬盘的程序命名)
-W<按回车> (把这10Bh 即267个字节写入文件)
-Q<按回车> (退出DEBUG)
PROMPT> DIR printhw.com<按回车>
将会汇报程序的长度是267字节(10Bh字节).
PROMPT> printhw.com<按回车>
运行这个程序,这将会在屏幕上显示出"Hello,World" :
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
-E 200<按回车> (从偏移地址200开始。输入"Hello,World") 200
48<按空格>65<按空格> (输入48h (H)和65h (e))
6C<按空格>6C<按空格> (输入6Ch (l)和6Ch (l))
6F<按空格>2C<按空格> (输入6Fh (o)和2Ch (,))
57<按空格>6F<按空格> (输入57h (W)和6Fh (o))
72<按空格>6C<按空格> (输入72h (r)和6Ch (l))
64<按空格>24<按空格> (输入64h (d)和24h ($))
<按回车> ("Hello,World" 已经输入完毕)
-D 200<按回车> (显示你刚刚输入的内容: 200
48 65 6C 6C 6F 2C 57 6F-72 6C 64 24 ... HELLO,WORLD$...)
--------------------------------------------------------------------------------------------------------
-A 100<按回车> (用汇编语言写一个新程序在IP-100h处开始)
MOV AH,09<按回车> (选择DOS的09号功能调用,显示字符串)
MOV DX,0200<按回车> (把输出地址(200h),放进寄存器) 0200
INT 21<按回车> (执行DOS功能调用,显示"Hello,World")
INT 20<按回车> (退出程序回到DOS状态)
<按回车> (结束汇编语言输入,回到DEBUG输入状态)
--------------------------------------------------------------------------------------------------------
-G<按回车> (从 CS:IP开始运行程序, 就是从107F:0100h开始执行程序)
--------------------------------------------------------------------------------------------------------
DEBUG.EXE指令说明
DEBUG
a 编写汇编语言程序的指令,sta为启始地址
c sta end sta2 比较两个储存单元,sta为第一储存单元的启始地址,而end为第一储存单元结束地址,sta2为第二储存单元的启始地址
c sta lnn sta2 比较两储存单元,sta为第一储存单元启始地址,而nn为欲比较的长度大小,sta2为第二储存单元启始地址
d 显示某指定范围储存单元至屏幕(sta:启始、end:结束)
d 显示某指范围块储存单元至屏幕(sta:启始、nn:长度)
e 修改储存单元中某一个byte的资料,sta为地址
e 修改储存单元中某一个byte的资料,data为新资料
g 执行程序,直至结束地址(end)或程序结束时
g=sta 执行从启始(sta)直至结束(end)或程序结束时
r 显示所有存储器内容或修改某指定存储器(reg)值
t 单步执行,num指定一次执行几步(预设1)
t=sta 单步执行,从sta起始,num指定执行几步(预设1)
n filename 为目前正在编辑或除错的文件命名
w 储存文件,写入cx个bytes的资料至n指定的文件名
w sta dri sec num 将sta资料写入dri磁盘的第sec磁区共写num个磁区
l 载入文件,读出n指定文件,档名的资料至sta地址中
l sta dri sec num 读出dri磁盘的第sec磁区的资料至sta共读num个磁区
q 离开debug,返回DOS
u 反汇编,从sta至end
u 反汇编,从sta,共反汇编nn个bytes
m sta end sta2 将第一储存单元的数据搬至第二储存单元中
m sta lnn sta2 将第一储存单元的数据搬至第二储存单元中
f sta end data 将一段资料(data)存入某指定的储存单元区
f sta lnn data 将nn个bytes的资料存入某指定的储存单元区
s sta end data 搜寻data资料在指定地址内,data不限长度
s sta lnn data 搜寻data资料在指定地址内,data不限长度
h data data2 计算两个资料的和与差并显示在屏幕上
i inport 由输入埠输入并显示一个byte
o outport 由输出埠输出一个byte值
Last edited by zzz19760225 on 2018-1-1 at 08:10 ]
作者: zzz19760225
时间: 2016-6-26 18:51
1
作者: zzz19760225
时间: 2016-6-26 18:52
1
作者: zzz19760225
时间: 2016-6-26 18:56
1
作者: zzz19760225
时间: 2016-6-26 18:58
1
作者: zzz19760225
时间: 2016-6-26 19:00
1
作者: zzz19760225
时间: 2016-6-26 19:02
1
作者: zzz19760225
时间: 2016-6-26 19:03
1
作者: zzz19760225
时间: 2016-6-26 19:07
1
作者: zzz19760225
时间: 2016-6-26 19:07
1
作者: zzz19760225
时间: 2016-6-26 19:08
1
作者: zzz19760225
时间: 2016-6-26 19:10
1
作者: zzz19760225
时间: 2016-6-26 19:10
1
作者: zzz19760225
时间: 2016-6-26 19:11
标题: gdb
gdb 免费编辑 添加义项名
B 添加义项 ?
所属类别 : 软件
UNIX及UNIX-like下的调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具相比于VC、z的优点是具有修复网络断点以及恢复链接等功能。BCB的图形化调试器更强大的功能。所谓"寸有所长,尺有所短"就是这个道理。
词条 百科 精彩信息一览无遗
基本信息
外文名称
GDB
发布组织
GNU开源组织
类型
强大的UNIX下的程序调试工具
功能
动态的改变你程序的执行环境等
目录
1功能
2版本发布
3文件清单
4执行程序
5显示数据
6断点
7断点管理
8变量检查赋值
9单步执行
10函数调用
11机器语言工具
12信号
13GDB使用
折叠编辑本段功能
一般来说,GDB主要帮助你完成下面四个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。
折叠编辑本段版本发布
2009年12月29日,程序调试工具 GDB 7.0.1 发布,新版本修正了7.0版本的一些严重的堆栈溢出bug,这些bug可能导致 GDB 调试进程中断,修正了在 FreeBSD 和 IRⅨ 系统下无法编译的问题,增加了对 Thumb2调试的支持,还有其他一些小bug的修复。
2010年03月19日,GDB 7.1 发布,
详细改进内容:多程序调试的支持;
位置独立的可执行文件(派)调试的支持;
新的目标(包括一个模拟器):Xilinx MicroBlaze和瑞萨RX;
Python支持增强;
c++支持扩展;
新tracepoint功能;
过程记录的改进;
远程协议扩展。
2010年09月06日 ,GDB 7.2 发布,
该版本改进记录:
⒈ 支持D语言
⒉ C++ 改进,支持参数依赖查找ADL,静态常量类成员和改进了用户自定义操作符的支持
⒊ Python 调试的改进,包括断点、符号、符号表、程序空间、线程等可通过命令行进行操作
⒋ Furthermore,enhancements were made for tracepoints and for GDBserver.在跟踪点和GDB程序上有了改善。
⒌ 支持 ARM Symbian 平台
⒍ 其他方面的改进和bug修复。
2011年08月26日,GDB 7.3a 发布,
变化:
1。GDB可以理解线程的名字。
2。这个命令"线程名称"(指定一个名称)和"线程找到"(匹配名称、目标ID,或者额外的信息)被添加。
3。Python脚本支持是大大增强。
4。在c++的支持,异常处理是提高,模板参数放在范围在一个实例化时调试。
5。线程调试的核心转储在GNU / Linux成为可能。
6。最初支持C语言版本的OpenCL。
7。许多其他改进。
折叠编辑本段文件清单
List
(gdb) list line1,line2
查看源代码
list lineNum 在lineNum的前后源代码显示出来
list + 列出当前行的后面代码行
list - 列出当前行的前面代码行
list function
set listsize count
设置显示代码的行数
show listsize
显示打印代码的行数
list first,last
显示从first到last的源代码行
折叠编辑本段执行程序
要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<;和>;)和shell通配符(*、?、)在内。如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。
(gdb) file a.out //加载被调试的可执行程序文件。
(gdb)set args –b –x
(gdb) show args
(gdb)r //执行程序
backtrace命令为堆栈提供向后跟踪功能。
Backtrace 命令产生一张列表,包含着从最近的过程开始的所有有效过程和调用这些过程的参数。
折叠编辑本段显示数据
利用print 命令可以检查各个变量的值。
(gdb) print p (p为变量名)
print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容:
对程序中函数的调用
(gdb) print find_entry(1,0)
数据结构和其他复杂对象
(gdb) print *table_start
={e=reference='\000',location=0x0,next=0x0}
值的历史成分
(gdb)print (为历史记录变量,在以后可以直接引用的值)
人为数组
人为数组提供了一种去显示存储器块(数组节或动态分配的存储区)内容的方法。早期的调试程序没有很好的方法将任意的指针换成一个数组。就像对待参数一样,让我们查看内存中在变量h后面的10个整数,一个动态数组的语法如下所示:
base@length
因此,要想显示在h后面的10个元素,可以使用h@10:
(gdb)print h@10
=(-1,345,23,-234,0,0,0,98,345,10)
whatis命令可以显示某个变量的类型
(gdb) whatis p
type = int *
折叠编辑本段断点
break命令(可以简写为b)可以用来在调试的程序中设置断点,该命令有如下四种形式:
break line-number 使程序恰好在执行给定行之前停止。
break function-name 使程序恰好在进入指定的函数之前停止。
break line-or-function if condition 如果condition(条件)是真,程序到达指定行或函数时停止。
break routine-name 在指定例程的入口处设置断点
如果该程序是由很多原文件构成的,你可以在各个原文件中设置断点,而不是在当前的原文件中设置断点,其方法如下:
(gdb) break filename:line-number
(gdb) break filename:function-name
要想设置一个条件断点,可以利用break if命令,如下所示:
(gdb) break line-or-function if expr
例:
(gdb) break 46 if testsize==100
从断点继续运行:continue 命令
折叠编辑本段断点管理
折叠1.显示当前gdb的断点信息:
(gdb) info break
他会以如下的形式显示所有的断点信息:
Num Type Disp Enb Address What
1 breakpoint keep y 0x000028bc in init_random at qsort2.c:155
2 breakpoint keep y 0x0000291c in init_organ at qsort2.c:168
删除指定的某个断点:
(gdb) delete breakpoint 1
该命令将会删除编号为1的断点,如果不带编号参数,将删除所有的断点
(gdb) delete breakpoint
禁止使用某个断点
(gdb) disable breakpoint 1
该命令将禁止断点1,同时断点信息的 (Enb)域将变为 n
允许使用某个断点
(gdb) enable breakpoint 1
该命令将允许断点1,同时断点信息的 (Enb)域将变为 y
清除源文件中某一代码行上的所有断点
(gdb)clear number
注:number 为源文件的某个代码行的行号
折叠2.设置条件断点
例子:
gdb可以设置条件断点,也就是只有在条件满足时,断点才会被触发,命令是"break … if cond"。以上面程序为例:
可以看到设定断点只在i的值为101时触发,此时打印sum的值为5050。
折叠编辑本段变量检查赋值
whatis:识别数组或变量的类型
ptype:比whatis的功能更强,他可以提供一个结构的定义
set variable = value:将值赋予变量
print variable = value or p variable = value : 除了显示一个变量的值外,还可以用来赋值
折叠编辑本段单步执行
next 不进入的单步执行
step 进入的单步执行如果已经进入了某函数,而想退出该函数返回到它的调用函数中,可使用命令finish
折叠编辑本段函数调用
call name 调用和执行一个函数
(gdb) call gen_and_sork(1234,1,0)
(gdb) call printf("abcd")
=4
finish 结束执行当前函数,显示其返回值(如果有的话)
折叠编辑本段机器语言工具
有一组专用的gdb变量可以用来检查和修改计算机的通用寄存器,gdb提供了目 前每一台计算机中实际使用的4个寄存器的标准名字:
$pc :程序计数器
$fp :帧指针(当前堆栈帧)
$sp :栈指针
$ps :处理器状态
折叠编辑本段信号
gdb通常可以捕捉到发送给它的大多数信号,通过捕捉信号,它就可决定对于正在运行的进程要做些什么工作。例如,按CTRL-C将中断信号发送给gdb,通常就会终止gdb。但是你或许不想中断gdb,真正的目的是要中断gdb正在运行的程序,因此,gdb要抓住该信号并停止它正在运行的程序,这样就可以执行某些调试操作。
Handle命令可控制信号的处理,他有两个参数,一个是信号名,另一个是接受到信号时该作什么。几种可能的参数是:
nostop 接收到信号时,不要将它发送给程序,也不要停止程序。
stop 接受到信号时停止程序的执行,从而允许程序调试;显示一条表示已接受到信号的消息(禁止使用消息除外)
print 接受到信号时显示一条消息
noprint 接受到信号时不要显示消息(而且隐含着不停止程序运行)
pass 将信号发送给程序,从而允许你的程序去处理它、停止运行或采取别的动作。
nopass 停止程序运行,但不要将信号发送给程序。
例如,假定你截获SIGPIPE信号,以防止正在调试的程序接受到该信号,而且只要该信号一到达,就要求该程序停止,并通知你。要完成这一任务,可利用如下命令:
(gdb) handle SIGPIPE stop print
请注意,UNⅨ的信号名总是采用大写字母!你可以用信号编号替代信号名如果你的程序要执行任何信号处理操作,就需要能够测试其信号处理程序,为此,就需要一种能将信号发送给程序的简便方法,这就是signal命令的任务。该命令的参数是一个数字或者一个名字,如SIGINT。假定你的程序已将一个专用的SIGINT(键盘输入,或CTRL-C;信号2)信号处理程序设置成采取某个清理动作,要想测试该信号处理程序,你可以设置一个断点并使用如下命令:
(gdb) signal 2
continuing with signal SIGINT⑵
该程序继续执行,但是立即传输该信号,而且处理程序开始运行。
折叠编辑本段GDB使用
GDB是一个强大的命令行调试工具。大家知道命令行的强大就是在于,其可以形成
执行序列,形成脚本。UNⅨ下的软件全是命令行的,这给程序开发提代供了极大的
便利,命令行软件的优势在于,它们可以非常容易的集成在一起,使用几个简单的已
有工具的命令,就可以做出一个非常强大的功能。
于是UNⅨ下的软件比Windows下的软件更能有机地结合,各自发挥各自的长处,组合
成更为强劲的功能。而Windows下的图形软件基本上是各自为营,互相不能调用,很
不利于各种软件的相互集成。在这里并不是要和Windows做个什么比较,所谓"寸有
所长,尺有所短",图形化工具还有时不如命令行的地方。
Last edited by zzz19760225 on 2017-11-13 at 14:07 ]
作者: zzz19760225
时间: 2016-6-26 19:14
1
作者: zzz19760225
时间: 2016-6-26 19:17
1
作者: zzz19760225
时间: 2016-6-26 19:19
1
作者: zzz19760225
时间: 2016-6-26 19:26
1
作者: zzz19760225
时间: 2016-6-26 19:27
1
作者: zzz19760225
时间: 2016-6-26 19:28
1
作者: zzz19760225
时间: 2016-6-26 19:33
1
作者: zzz19760225
时间: 2016-6-26 19:34
1
作者: zzz19760225
时间: 2016-6-26 19:35
1
作者: zzz19760225
时间: 2016-6-26 19:36
1
作者: zzz19760225
时间: 2016-6-26 19:37
1
作者: zzz19760225
时间: 2016-6-26 19:38
1
作者: zzz19760225
时间: 2016-6-26 19:40
1
作者: zzz19760225
时间: 2016-6-26 19:40
1
作者: zzz19760225
时间: 2016-6-26 19:42
bit#
R-type
add
addu
sub
subu
and
or
xor
nor
slt
sltu
sll
srl
sra
sllv
srlv
srav
jr
I-type
addi
addiu
andi
ori
xori
lui
lw
sw
beq
bne
slti
sltiu
J-type
j
jal
Last edited by zzz19760225 on 2017-9-18 at 21:13 ]
作者: zzz19760225
时间: 2016-6-26 19:42
1
作者: zzz19760225
时间: 2016-6-26 19:43
1
作者: zzz19760225
时间: 2016-6-26 19:44
1
作者: zzz19760225
时间: 2016-6-26 19:44
1
作者: zzz19760225
时间: 2016-6-26 19:46
1
作者: zzz19760225
时间: 2016-6-26 19:47
1
作者: zzz19760225
时间: 2016-6-26 19:48
1
作者: zzz19760225
时间: 2016-6-26 19:50
1
作者: zzz19760225
时间: 2016-6-26 19:51
1
作者: zzz19760225
时间: 2016-6-26 19:51
1
作者: zzz19760225
时间: 2016-6-26 19:52
1
作者: zzz19760225
时间: 2016-6-26 19:53
1
作者: zzz19760225
时间: 2016-6-26 19:54
1
作者: zzz19760225
时间: 2016-6-26 19:54
1
作者: zzz19760225
时间: 2016-6-26 19:55
标题: CM\P汇编
; COMMON DATA FOR CP/M ASSEMBLER MODULE
ORG 100H
ENDA EQU 20F0H ;END OF ASSEMBLER PROGRAM
BDOS EQU 5H ;ENTRY TO DOS, USED TO COMPUTE END MEMORY
LXI SP, ENDMOD
LHLD BDOS+1
SHLD SYMAX ;COMPUTE END OF MEMORY
JMP ENDMOD
;
; PRINT BUFFER AND PRINT BUFFER POINTER
PBMAX EQU 120 ;MAX PRINT BUFFER
PBUFF:
DS PBMAX
PBP:
DS 1 ;PRINT BUFFER POINTER
;
; SCANNER PARAMETERS
TOKEN:
DS 1 ;CURRENT TOKEN
VALUE:
DS 2 ;BINARY VALUE FOR NUMBERS
ACCLEN:
DS 1 ;ACCUMULATOR LENGTH
ACMAX EQU 64 ;LENGTH OF ACCUMULATOR
ACCUM:
DS ACMAX ;ACCUMULATOR (MUST FOLLOW ACCLEN)
;
; OPERAND EXPRESSION EVALUATOR PARAMETERS
EVALUE:
DS 2 ;VALUE OF EXPRESSION AFTER EVALUATION
;
; SYMBOL TABLE MODULE PARAMETERS
SYTOP:
DW ENDA ;FIRST LOCATION AVAILABLE FOR SYMBOL TABLE
SYMAX:
DS 2 ;LAST AVAILABLE LOCATION FOR SYMBOL TABLE
;
; MISCELLANEOUS DATA AREAS
PASS:
DS 1 ;PASS # 0,1
FPC:
DS 2 ;FILL ADDRESS FOR NEXT HEX RECORD
ASPC:
DS 2 ;ASSEMBLER'S PSEUDO PC
SYBAS:
DW ENDA ;SYMBOL TABLE BASE
SYADR:
DS 2 ;CURRENT SYMBOL BASE
ENDMOD EQU ($ AND 0FF00H)+100H
END
; I/O MODULE FOR CP/M ASSEMBLER
;
ORG 206H
BOOT EQU SOCH ;REBOOT LOCATION
;I/O MODULE ENTRY POINTS
JMP INIT ;INITIALIZE, START ASSEMBLER
JMP SETUP ;FILE SETUP
JMP GNC ;GET NEXT CHARACTER
JMP PNC ;PUT NEXT OUTPUT CHARACTER
JMP PNB ;PUT NEXT HEX BYTE
JMP PCHAR ;PRINT CONSOLE CHARACTER
JMP PCON ;PRINT CONSOLE BUFFER TO CRLF
JMP WOBUFF ;WRITE OUTBUFFER
JMP PERR ;PLACE ERROR CHARACTER INTO PBUFF
JMP DHEX ;PLACE HEX BYTE INTO OUTPUT BUFFER
JMP EOR ;END OF ASSEMBLY
; DATA FOR I/O MODULE
BPC:
DS 2 ;BASE PC FOR CURRENT HEX RECORD
DBL:
DS 1 ;HEX BUFFER LENGTH
DBUFF:
DS 16 ;HEX BUFFER
;
; DISK NAMES
CDISK DS 1 ;CURRENTLY SELECTED DISK
ADISK DS 1 ;.ASM DISK
PDISK:
DS 1 ;.PRN DISK
HDISK:
DS 1 ;.HEX DISK
;
;
; COMMON EQUATES
QBMAX EQU 120 ;MAX PRINT SIZE
QBUFF EQU 10CH ;PRINT BUFFER
QBP EQU QBUFF+QBMAX ;PRINT BUFFER POINTER
;
TOKEN EQU QBP+1 ;CURRENT TOKEN USER SCAN
VALUE EQU TOKEN+l ;VALUE OF NUMBER IN BINARY
ACCLEN EQU VALUE+2 ;ACCUMULATOR LENGTH
ACMAX EQU 64 ;MAX.ACCUMULATOR LENGTH
ACCUM EQU ACCLEN+1
;
EVALUE EQU ACCUM+ACMAX ;VALUE FROM EXPRESSION ANALYSIS
;
SYTOP EQU EVALUE+2 ;CURRENT SYMBOL TOP
SYMAX EQU SYTOP+2 ;MAX ADDRESS+1
;
PASS EQU SYMAX+2 ;CURRENT PASS NUMBER
FPC EQU PASS+1 ;PILL ADDRESS FOR DHEX ROUTINE
ASPC EQU FPC+2 ;ASSEMBLER'S PSEUDO PC
;
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
EOF EQU 1AH ;END OF FILE MARK
;
;
; DOS ENTRY POINTS
BDOS EQU 5H ;DOS ENTRY POINT
READC EQU 1 ;READ CONSOLE DEVICE
WRITC EQU 2 ;WRITE CONSOLE DEVICE
REDYC EQU 11 ;CONSOLE CHARACTER READY
SELECT EQU 14 ;SELECT DISK SPECIFIED BY REGISTER E
OPENF EQU 15 ;OPEN FILE
CLOSF EQU 16 ;CLOSE FILE
DELEF EQU 19 ;DELETE FILE
READF EQU 20 ;READ FILE
WRITF EQU 21 ;WRITE FILE
MAKEF EQU 22 ;MAKE A FILE
CSEL EQU 25 ;RETURN CURRENTLY SELECTED DISK
SETDM EQU 26 ;SET DMA ADDRESS
;
; FILE AND BUFFERING PARAMETERS
NSB EQU 8 ;NUMBER OF SOURCE BUFFERS
NPB EQU 6 ;NUMBER OF PRINT BUFFERS
NHB EQU 6 ;NUMBER OF HEX BUFFERS
;
SSIZE EQU NSB*128
PSIZE EQU NPB*128
ESIZE EQU NHB*128
;
; FILE CONTROL BLOCKS
SCB:
DS 9 ;FILE NAME
DB 'ASM' ;FILE TYPE
SCBR:
DS 1 ;REEL NUMBER (ZEROED IN SETUP)
DS 19 ;MISC AND DISK MAP
SCBCR:
DS 1 ;CURRENT RECORD (ZEROED IN SETUP)
;
PCB:
DS 9
DB 'PRN', 0
DS 19
DB 0 ;RECORD TO WRITE NEXT
;
HCB:
DS 9
DB 'HEX', 0
DS 19
DB 0
;
; POINTERS AND BUFFERS
SBP:
DW SSIZE ;NEXT CHARACTER POSITION TO READ
SBUFF:
DS SSIZE
;
PBP:
DW 0
PBUFF:
DS PSIZE
;
HBP:
DW 0
HBUFF:
DS HSIZE
FCB EQU SCH ;FILE CONTROL BLOCK ADDRESS
FNM EQU 1 ;POSITION OF FILE NAME
FLN EQU 9 ;FILE NAME LENGTH
DUFF EQU 80H ;INPUT DISK BUFFER ADDRESS
;
SEL: ;SELECT DISK IN REG-A
LXI H, CDISK
CMP M ;SAME?
RZ
MOV M, A ;CHANGE CURRENT DISK
MOV E, A
MVI C, SELECT
CALL BDOS
RET
;
SCNP: ;SCAN THE NEXT PARAMETER
INX H
MOV A, M
CPI ' '
JZ SCNP0
SBI 'A' ;NORMALIZE
RET
SCNP0:
LDA CDISK
RET
;
PCON: ;PRINT MESSAGE AT H,L TO CONSOLE DEVICE
MOV A, M
CALL PCHAR
MOV A, M
INX H
CPI CR
JNZ PCON
MVI A, LF
CALL PCHAR
RET
;
FNAME: ;FILL NAME FROM DEFAULT FILE CONTROL BLOCK
LXI D, FCB
MVI B, FLN
FNAM0:
LDAX D ;GET NEXT FILE CHARACTER
CPI '?'
JZ FNERR ;FILE NAME ERROR
MOV M, A ;STORE TO FILE CNTRL BLOCK
INX H
INX D
DCR B
JNZ FNAM0 ;FOR NEXT CHARACTER
RET
;
INIT: ;SET UP STACK AND FILES, START ASSEMBLER
LXI H ;TITL
CALL PCON
JMP SET0
;
OPEN: ;OPEN FILE ADDRESSED BY D,E
MVI C ;OPENF
CALL BDOS
CPI 255
RNZ
;OPEN ERROR
LXI H, ERROP
CALL PCON
JMP BOOT
;
CLOSE: ;CLOSE FILE ADDRESSED BY D,E
MVI C, CLOSF
CALL BDOS
CPI 255
RNZ ;CLOSE OK
LXI H, ERRCL
CALL PCON
JMP BOOT
;
DELETE: ;DELETE FILE' ADDRESSED BY D,E
MVI C, DELEF
JMP BDOS
;
MAKE: ;MAKE FILE ADDRESSED BY D,E
MVI C, MAKEF
CALL BDOS
CPI 255
RNZ
;MAKE ERROR
LXI H, ERRMA
CALL PCON
JMP BOOT
;
SELA:
LDA ADISK
CALL SEL
RET
;
NPR: ;RETURN ZERO FLAG IF NO PRINT FILE
LDA PDISK
CPI 'Z'-'A'
RZ
CPI 'X'-'A' ;CONSOLE:
RET
;
SELP:
LDA PDISK
CALL SEL
RET
;
SELH:
LDA HDISK
CALL SEL
RET
;
SET0: ;SET UP FILES FOR INPUT AND OUTPUT
LDA FCB ;GET FIRST CHARACTER
CPI ;MAY HAVE FORGOTTEN NAME
JZ FNERR ;FILE NAME ERROR
MVI C, CSEL ;CURRENT DISK?
CALL BDOS ;GET IT TO REG
STA CDISK
;
; SCAN PARAMETERS
LXI H, FCB+FLN-1
CALL SCNP
STA ADISK
CALL SCNP
STA HDISK
CALL SCNP
STA PDISK
;
LXI H, SCB ;ADDRESS SOURCE FILE CONTROL BLOCK
CALL FNAME ;FILE NAME OBTAINED FROM DEFAULT FCB
;
CALL NPR ;Z OR X?
JZ NOPR
LXI H, PCB ;ADDRESS PRINT FILE CONTROL BLOCK
PUSH H ;SAVE A COPY FOR OPEN
PUSH H ;SAVE A COPY FOR DELETE
CALL FNAME ;FILL PCB
CALL SELP
POP D ;FCB ADDRESS
CALL DELETE
POP D ;FCB ADDRESS?
CALL MAKE
;
NOPR: ;TEST FOR HEX FILE
LDA HDISK
CPI 'Z'-'A'
JZ NOHEX
LXI H, HCB
PUSH H
PUSH H
CALL FNAME
CALL SELH
POP D
CALL DELETE
POP D
CALL MAKE
;
; FILES SET UP, CALL ASSEMBLER
NOHEX:
JMP ENDMOD
;
SETUP: ;SETUP INPUT FILE FOR SOURCE PROGRAM
LXI H, SSIZE
SHLD SBP ;CAUSE IMMEDIATE READ
XRA A ;ZERO VALUE
STA SCBR ;CLEAR REEL NUMBER
STA SCBCR ;CLEAR CURRENT RECORD
STA DBL ;CLEAR HEX BUFFER LENGTH
CALL SELA
LXI D, SCB
CALL OPEN
;
RET
;
FNERR: ;FILE NAME ERROR
LXI H, ERRFN
CALL PCON
JMP BOOT
;
;
GCOMP: ;COMPARE D,E AGAINS H,L
MOV A, D
CMP H
RNZ
MOV A, E
CMP L
RET
;
GNC: ;GET NEXT CHARACTER FROM SOURCE BUFFER
PUSH B
PUSH D
PUSH H ;ENVIRONMENT SAVED
LHLD SBP
LXI D ;SSIZE
CALL GCOMP
JNZ GNC2
;
;READ ANOTHER BUFFER
CALL SELA
LXI H, 0
SHLD SBP
MVI B, NSB ;NUMBER OF SOURCE BUFFERS
LXI H, SBUFF
GNC0: ;READ 128 BYTES
PUSH B ;SAVE COUNT
PUSH H ;SAVE BUFFER ADDRESS
MVI C, READF
LXI D, SCB
CALL BDOS ;PERFORM THE READ
POP H ;RESTORE BUFFER ADDRESS
POP B ;RESTORE BUFFER COUNT
ORA A ;SET FLAGS
MVI C, 128
JNZ GNC1
;NORMAL READ OCCURRED
LXI D, BUFF ;SOURCE BUFFER ADDRESS
MVI C, 128
MOV0:
LDAX D ;GET CHARACTER
MOV M, A ;STORE CHARACTER
INX D
INX H
DCR C
JNZ MOV0
;BUFFER LOADED, TRY NEXT BUFFER
;
DCR B
JNZ GNC0
JMP GNC2
;
GNCl: ;EOF OR ERROR
CPI 3 ;ALLOW 0,1,2
JNC FRERR ;FILE READ ERROR
GNCE:
MVI M, EOF ;STORE'AND END OF FILE CHARACTER
INX H
DCR C
JNZ GNCE ;FILL CURRENT BUFFER WITH EOF'S
;
GNC2: ;GET CHARACTER TO ACCUMULATOR AND RETURN
LXI D, SBUFF
LHLD SBP
PUSH H ;SAVE CURRENT SBP
INX H ;READY FOR NEXT READ
SHLD SBP
POP H ;RESTORE PREVIOUS SBP
DAD D ;ABSOLUTE ADDRESS OF CHARACTER
MOV A, M ;GET IT
POP H
POP D
POP B
RET
;
FRERR:
LXI H, ERRFR
CALL PCON ;PRINT READ ERROR MESSAGE
JMP BOOT
;
PNC: ;SAME AT PNCF, BUT ENVIRONMENT IS SAVED FIRST
PUSH B
;CHECK FOR CONSOLE OUTPUT /'NO OUTPUT
MOV B, A ;SAVE CHARACTER
LDA PDISK ;Z OR X?
CPI 'Z'-'A' ;Z NO OUTPUT
JZ PNRET
;
CPI 'X'-'A'
MOV A, B ;RECOVER CHAR FOR CON OUT
JNZ PNGO
CALL PCHAR
JMP PNRET
;
;NOT X OR Z, SO PRINT IT
PNGO:
PUSH D
PUSH H
CALL PNCF
POP H
POP D
PNRET:
POP B
RET
;
PNCF: ;PRINT NEXT CHARACTER
LHLD PBP
XCHG
LXI H, PBUFF
DAD D
MOV M, A ;CHARACTER STORED AT PBP IN PBUFF
XCHG ;PBP TO H,L
INX H ;POINT TO NEXT CHARACTER
SHLD PBP ;REPLACE IT
XCHG
LXI H, PSIZE
CALL GCOMP ;AT END OF BUFFER?
RNZ ;RETURN IF NOT
;
;OVERFLOW, WRITE BUFFER
CALL SELP
LXI H, 0
SHLD PSP
LXI H, PBUFF
LXI D, PCB ;D,E ADDRESS FILE CONTROL BLOCK
MVI B, NPS ;NUMBER OF BUFFERS TO B
; (DROP THROUGH TO WBUFF)
;
WBUFF: ;WRITE BUFFERS STARTING AT H,L FOR B BUFFERS
; CHECK FOR EOF'S
MOV A, M
CPI EOF
RZ ;DON'T DO THE WRITE
;
PUSH B ;SAVE NUMBER OF BUFFERS
PUSH D ;SAVE FCB ADDRESS
MVI C, 128 ;READY FOR MOVE
LXI D, BUFF
WBUF0: ;MOVE TO BUFFER
MOV A, M ;GET CHARACTER
STAX D ;PUT CHARACTER
INX H
INX D
DCR C
JNZ WBUF0
;
;WRITE BUFFER
POP D ;RECOVER FCB ADDRESS
PUSH D ;SAVE IT AGAIN FOR LATER
PUSH H ;SAVE BUFFER ADDRESS
MVI C, WRITF ;DOS WRITE FUNCTION
CALL BDOS
POP H ;RECOVER BUFFER ADDRESS
POP D ;RECOVER FCB ADDRESS
POP B ;RECOVER BUFFER COUNT
ORA A ;SET ERROR RETURN FLAGS
JNZ FWERR
;
;WRITE OX
DCR B
RZ ;RETURN IF NO' MORE BUFFERS TO WRITE
JMP WBUFF
;
FWERR: ;ERROR IN WRITE
LXI H, ERRFW
CALL PCON ;ERROR MESSAGE OUT
JMP EORC ;TO CLOSE AND REBOOT
;
;
PNB: ;PUT NEXT HEX BYTE
PUSH B
PUSH D
PUSH H
CALL PNBF
POP H
POP D
POP B
RET
;
PNBF: ;PUT NEXT BYTE
; (SIMILAR TO THE PNCF SUBROUTINE)
LHLD HBP
XCHG
LXI H, HBUFF
DAD D
MOV M, A ;CHARACTER STORED AT HBP IN HBUFF
XCHG
INX H ;HBP INCREMENTED
SHLD HBP
XCHG ;BACK TO D,E
LXI H, HSIZE
CALL GCOMP ;EQUAL?
RNZ
;
;OVERFLOW, WRITE BUFFERS
CALL SEDH
LXI H, D
SHLD HBP
LXI H, HBUFF
LXI D, HCB ;FILE CONTROL BLOCK FOR HEX FILE
MVI B, NHB
JMP WBUFF ;WRITE BUFFERS
;
PCHAR: ;PRINT CHARACTER IN REGISTER A
PUSH B
PUSH D
PUSH H
MVI C, WRITC
MOV E, A
CALL BDOS
POP H
POP D
POP B
RET
;
WOCHAR: ;WRITE CHARACTER IN REG-A WITH REFLECT AT CONSOLE IF EB
MOV C, A ;SAVE THE CHAR
CALL PNC ;PRINT CHAR
LDA QBUFF
CPI
RZ
;ERROR IN LINE
LDA PDISK
CPI 'X'-'A'
RZ ;ALREADY PRINTED IF 'X'
;
MOV A, C ;RECOVER CHARACTER
CALL PCHAR ;PRINT IT
RET
;
WOBUFF: ;WRITE THE OUTPUT BUFFER TO THE PRINT FILE
LDA QBP ;GET CHARACTER COUNT
LXI H, QBUFF ;BASE OF BUFFER
WOB0:
ORA A ;ZER0 COUNT?
JZ WOBE
;NOT END, SAVE COUNT AND GET CHARACTER
MOV B, A ;SAVE COUNT
MOV A, M
CALL WOCHAR ;WRITE CHARACTER
INX H ;ADDRESS NEXT CHARACTER OF BUFFER
MOV A, B ;GET COUNT
DCR A
JMP WOB0
;
WOBE: ;END OF PRINT - ZERO QBP
STA QBP
;FOLLOW BY CR LF
MVI A, CR
CALL WOCHAR
MVI A, LF
CALL WOCHAR
LXI H, QBUFF
MVI A, QBMAX ;READY TO BLANK OUT
WOB2:
MVI M,' '
INX H
DCR A
JNZ WOB2
RET
;
;
PERR: ;FILL QBUFF ERROR MESSAGE POSITION
MOV B, A ;SAVE CHARACTER
LXI H, QBUFF
MOV A, M
CPI ' '
RNZ ;DON'T CHANGE IT IF ALREADY SET
MOV M, B ;STORE ERROR CHARACTER
RET
;
EOR: ;END OF ASSEMBLER
CALL NPR ;Z OR A?
JZ EOPR
;FILL OUTPUT FILES WITH EOF'S
EOR2:
LHLD PBP
MOV A, L
ORA H ;VALUE ZERO?
JZ EOPR
MVI A, EOF ;CTL-Z IS END OF FILE
CALL PNC ;PUT ENDFILES IN PRINT BUFFER
JMP EOR2 ;EVENTUALLY BUFFER IS WRITTEN
;
EOPR: ;END 0F PRINT PILE, CHECK HEX
LDA HDISK
CPI 'Z'-'A'
JZ EORC
EOR0: ;WRITE TERMINATING RECORD INTO HEX FILE
LDA DBL ;MAY BE ZERO ALREADY
ORA A
CNZ WHEX ;WRITE HEX BUFFER IF NOT ZERO
LHLD FPC ;GET CURRENT FPC AS LAST ADDRESS
SHLD BPC ;RECORD LENGTH ZERO, BASE ADDRESS 0000
CALL WHEX ;WRlTE HEX BUFFER
;
;NOW CLEAR OUTPUT BUFFER FOR HEX FILE
EOR1:
LHLD HBP
MOV A, L
ORA H
JZ EORC
MVI A, EOF
CALL PNB
JMP EOR1
;
; CLOSE FILES AND TERMINATE
EORC:
CALL NPR
JZ EORPC
CALL SELP
LXI D, PCB
CALL CLOSE
EORPC:
LDA HDISK
CPI 'Z'-'A'
JZ EORHC
CALL SELH
LXI D, HCB
CALL CLOSE
;
EORHC:
LXI H, ENDA
CALL PCON
JMP BOOT
;
TITL:
DB 'CP/M ASSEMBLER - VER 1.0', CR
ERROP:
DB 'NO SOURCE FILE PRESENT', CR
ERRMA:
DB 'NO DIRECTORY SPACE', CR
ERRFN:
DB 'SOURCE FILE NAME ERROR', CR
ERRFR:
DB 'SOURCE FILE READ ERROR', CR
ERRFW:
DB 'OUTPUT FILE WRITE ERROR', CR
ERRCL:
DB 'CANNOT CLOSE FILES', CR
PENDA:
DB 'END OF ASSEMBLY', CR
;
DHEX: ;DATA TO HEX BUFFER (BYTE IN REG-A)
PUSH B
MOV B, A ;HOLD CHARACTER FOR 'Z' TEST
LDA HDISK
CPI 'Z'-'A'
MOV A, B ;RECOVER CHARACTER
JZ DHRET
PUSH D ;ENVIRONMENT SAVED
PUSH PSW ;SAVE DATA BYTE
LXI H, DBL ;CURRENT LENGTH
MOV A, M ;TO ACCUM
ORA A ;ZERO?
JZ DHEX3
;
;LENGTH NOT ZERO, MAY BE FULL BUFFER
CPI 16
JC DHEX1 ;BR IF LESS THAN 16 BYTES
;BUFFER FULL, DUMP IT
CALL WHEX ;DBL = 0 UPON RETURN
JMP DHEX3 ;SET BPC AND DATA BYTE
;
DHEX1: ;PARTIAL BUFFER IN PROGRESS, CHECK FOR SEQUENTIAL BYTE LOAD
LHLD FPC
XCHG
LHLD BPC ;BASE PC IN H,L
MOV C, A ;CURRENT LENGTH OF BUFFER
MVI B, 0 ;IS IN B,C
DAD B ;BPC+DBL TO H,L
MOV A, E ;READY FOR COMPARE
CMP L ;EQUAL?
JNZ DHEX2 ;BR IF NOT
MOV A, D ;CHECK HO BYTE
CMP H
JZ DHEX4 ;BR IF SAME ADDRESS
;
DHEX2: ;NON SEQUENTIAL ADDRESS, DUMP AND CHANGE BASE ADDRESS
CALL WHEX
DHEX3: ;SET NEW BASE
LHLD FPC
SHLD BPC
;
DHEX4: ;STORE DATA BYTE AND INC DBL
LXI H, DBL
MOV E, M ;LENGTH TO REG-E
INR M ;DBL=DBL+1
MVI D, 0 ;HIGH ORDER ZERO FOR DOUBLE ADD
LXI H, DBUFF
DAD D ;DBUFF+DBL TO H,L
POP PSW ;RESTORE DATA BYTE
MOV M, A ;INTO DATA BUFFER
POP D
DHRET:
POP B ;ENVIRONMENT RESTORED
RET
;
WRC: ;WRITE CHARACTER WITH CHECK SUM IN D
PUSH PSW
RRC
RRC
RRC
RRC
ANI 0FH
CALL HEXC ;OUTPUT HEX CHARACTER
POP PSW ;RESTORE BYTE
PUSH PSW ;SAVE A VERSION
ANI 0FH
CALL HEXC ;WRITE LOW NIBBLE
POP PSW ;RESTORE BYTE
ADD D ;COMPUTE CHECKSUM
MOV D, A ;SAVE CS
RET
;
HEXC: ;WRITE CHARACTER
ADI 90H
DAA
ACI 40H
DAA
JMP PNB ;PUT BYTE
;
WHEX: ;WRITE CURRENT HEX BUFFER
MVI A, ':' ;RECORD HEADER
CALL PNB ;PUT BYTE
LXI H, DBL ;RECORD LENGTH ADDRESS
MOV E, M ;LENGTH TO REG-E
XRA A ;ZERO TO REG-A
MOV D, A ;CLEAR CHECKSUM
MOV M, A ;LENGTH IS ZEROED FOR NEXT WRITE
LHLD BPC ;BASE ADDRESS FOR RECORD
MOV A, E ;LENGTH TO A
CALL WRC ;WRITE HEX VALUE
MOV A, H ;HIGH ORDER BASE ADDR
CALL WRC ;WRITE HO BYTE
MOV A, L ;LOW ORDER BASE ADDR
CALL WRC ;WRITE LO BYTE
XRA A ;ZERO TO A
CALL WRC ;WRITE RECORD TYPE 00
MOV A, E ;CHECK FOR LENGTH 0
ORA A
JZ WHEX1
;
;NON - ZERO, WRITE DATA BYTES
LXI H, DBUFF
WHEX0:
MOV A, M ;GET BYTE
INX H
CALL WRC ;WRITE DATA BYTE
DCR E ;END OF BUFFER?
JNZ WHEX0
;
;END OF DATA BYTES, WRITE CHECK SUM
WHEX1:
XRA A
SUB D ;COMPUTE CHECKSUM
CALL WRC
;
;SEND CRLF AT END OF RECORD
MVI A, CR
CALL PNB
MVI A, LF
CALL PNB
RET
;
;
;
ENDMOD EQU ($ AND 0FFE0H)+20H
END
ORG 1100H
JMP ENDMOD ;END OF THIS MODULE
JMP INITS ;INITIALIZE THE SCANNER
JMP SCAN ;CALL THE SCANNER
;
;
; ENTRY POINTS IN I/O MODULE
IOMOD EQU 200H
GNCF EQU IOMOD+6H
WOBUFF EQU IOMOD+15H
PERR EQU IOMOD+18H
;
LASTC:
DS 1 ;LAST CHAR SCANNED
NEXTC:
DS 1 ;LOOK AHEAD CHAR
STYPE:
DS 1 ;RADIX INDICATOR
;
; COMMON EQUATES
PBMAX EQU 120 ;MAX PRINT SIZE
PBUFF EQU 10CH ;PRINT BUFFER
PBP EQU PBUFF+PBMAX ;PRINT BUFFER POINTER
;
TOKEN EQU PEP+1 ;CURRENT TOKEN UDER SCAN
VALUE EQU TOKEN+1 ;VALUE OF NUMBER IN BINARY
ACCLEN EQU VALUE+2 ;ACCUMULATOR LENGTH
ACMAX EQU 64 ;MAX ACCUMULATOR LENGTH
ACCUM EQU ACCLEN+1
;
EVALUE EQU ACCUM+ACMAX ;VALUE FROM EXPRESSION ANALYSIS
;
SYTOP EQU EVALUE+2 ;CURRENT SYMBOL TOP
SYMAX EQU SYTOP+2 ;MAX ADDRESS+1
;
PASS EQU SYMAX+2 ;CURRENT PASS NUMBER
FPC EQU PASS+1 ;FILL ADDRESS FOR NEXT HEX BYTE
ASPC EQU FPC+2 ;ASSEMBLER'S PSEUDO PC
;
; GLOBAL EQUATES
IDEN EQU 1 IDENTIFIER
NUMB EQU 2 ;NUMBER
STRNG EQU 3 ;STRING
SPECL EQU 4 ;SPECIAL CHARACTER
;
PLABT EQU 0001B ;PROGRAM LABEL
DLABT EQU 0010B ;DATA LABEL
EQUT EQU 0100B ;EQUATE
SETT EQU 0101B ;SET
MACT EQU 0110B ;MACRO
;
EXTT EQU 1000B ;EXTERNAL
REFT EQU 1011B ;REFER
GLBT EQU 1100B ;GLOBAL
;
BINV EQU 2
OCTV EQU 8
DECV EQU 10
HEXV EQU 16
CR EQU 0DH
LF EQU 0AH
EOF EQU 1AH
TAB EQU 09H ;TAB CHARACTER
;
;
; UTILITY SUBROUTINES
GNC: ;GET NEXT CHARACTER AND ECHO TO PRINT FILE
CALL GNCF
PUSH PSW
CPI CR
JZ GNC0
CPI LF ;IF LF THEN DUMP CURRENT BUFFER
JZ GNC0
;
;NOT A CR OR LF, PLACE INTO BUFFER IF THERE IS ENOUGH ROOM
LDA PBP
CPI PBMAX
JNC GNC0
;ENOUGH ROOM, PLACE INTO BUFFER
MOV E, A
MVI D, 0 ;DOUBLE PRECISION PBP IN D,E
INR A
STA PBP ;INCREMENTED PBP IN MEMORY
LXI H, PBUFF
DAD D ;PBUFF(PBP)
POP PSW
MOV M, A ;PBUFF(PBP) - CHAR
RET
GNC0: ;CHAR NOT PLACED INTO BUFFER
POP PSW
RET
;
INITS: ;INITIALIZE THE'SCANNER
CALL ZERO
STA NEXTC ;CLEAR NEXT CHARACTER
STA PBP
MVI A, LF ;SET LAST CHAR TO LF
STA LASTC
CALL WOBUFF ;CLEAR BUFFER
MVI A, 16 ;START OF PRINT LINE
STA PBP
RET
;
ZERO:
XRA A
STA ACCLEN
STA STYPE
RET
;
SAVER: ;STORE THE NEXT CHARACTER INTO THE ACCUMULATOR AND UPDATE ACCLEN
LXI H, ACCLEN
MOV A, M
CPI ACMAX
JC SAV1 ;JUMP IF NOT UP TO LAST POSITION
MVI M, 0
CALL ERRO
SAV1:
MOV E, M ;D,E WILL HOLD INDEX
MVI D, 0
INR M ;ACCLEN INCREMENTED
INX H ;ADDRESS ACCUMULATOR
DAD D ;ADD INDEX TO ACCUMULATOR
LDA NEXTC ;GET CHARACTER
MOV M, A ;INTO ACCUMULATOR
RET
;
TDOLL: ;TEST FOR DOLLAR SIGN, ASSUMING H,L ADDRESS NEXTC
MOV A, M
CPI '$'
RNZ
XRA A ;TO GET A ZERO
MOV M, A ;CLEARS NEXTC
RET ;WITH ZERO FLAG SET
;
NUMERIC: ;CHECK NEXTC FOR NUMERIC, RETURN ZERO FLAG IF NOT NUMERIC
LDA NEXTC
SUI '0'
CPI 10
;CARRY RESET IF NUMERIC
RAL
ANI 1B ;ZERO IF NOT NUMERIC
RET
;
HEX: ;RETURN ZERO FLAG IF NEXTC IS NOT HEXADECIMAL
CALL NUMERIC
RNZ ;RETURNS IF 0-9
LDA NEXTC
SUI 'A'
CPI 6
;CARRY SET IF OUT OF RANGE
RAL
ANI 1B
RET
;
LETTER: ;RETURN ZERO FLAG IF NEXTC IS NOT A LETTER
LDA NEXTC
SUI 'A'
CPI 26
RAL
ANI 1B
RET
;
ALNUM: ;RETURN ZERO FLAG IF NOT ALPHANUMERIC
CALL LETTER
RNZ
CALL NUMERIC
RET
;
TRANS: ;TRANSLATE TO UPPER CASE
LDA NEXTC
CPI 'A' OR 1100000B ;LOWER CASE A
RC ;CARRY IF LESS THAN LOWER A
CPI ('Z' OR 1100000B)+1 ;LOWER CASE Z
RNC ;NO CARRY IF GREATER THAN LOWER
ANI 10111110 ;CONVERT TO UPPER CASE
STA NEXTC
RET
;
GNCN: ;GET CHARACTER AND STORE TO NEXTC
CALL GNC
STA NEXTC
CALL TRANS ;TRANSLATE TO UPPER CASE
RET
;
EOLT: ;END OF LINE TEST FOR COMMENT SCAN
CPI CR
RZ
CPI EOF
RZ
CPI '!'
RET
;
SCAN: ;FIND NEXT TOKEN IN INPUT STREAM
XRA A
STA TOKEN
CALL ZERO
;
; DEBLANK
DEBL:
LDA NEXTC
CPI TAB ;TAB CHARACTER TREATED AS BLANK OUTSIDE STRING
JZ DEB0
CPI ';' ;MAY BE A COMMENT
JZ DEB1 ;DEBLANK THROUGH COMMENT
CPI '*' ;PROCESSOR'TECH COMMENT
JNZ DEB2 ;NOT *
LDA LASTC
CPI LF ;LAST LINE FEED?
JNZ DEB2 ;NOT LF*
;COMMENT FOUND, REMOVE IT
DEB1:
CALL GNCN
CALL EOLT ;CR, EOF, OR !
JZ FINDL ;HANDLE END OF LINE
JMP DEB1 ;OTHERWISE CONTINUE SCAN
DEB2:
ORI ' ' ;MAY BE ZERO
CPI ' '
JNZ FINDL
DEB0:
CALL GNCN ;GET NEXT AND STORE'TO NEXTC
JMP DEBL
;
; LINE DEBLANKED, FIND TOKEN TYPE
FINDL: ;LOOK FOR LETTER, DECIMAL DIGIT, OR STRING QUOTE
CALL LETTER
JZ FIND0
MVI A, IDEN
JMP STOKEN
;
FIND0:
CALL NUMERIC
JZ FIND1
MVI A, NUMB
JMP STOKEN
;
FIND1:
LDA NEXTC
CPI ''''
JNZ FIND2
XRA A
STA NEXTC ;D0N'T STORE THE QUOTE
MVI A, STRNG
JMP STOKEN
;
FIND2: ;ASSUME IT IS A SPECIAL CHARACTER
CPI LF ;IF LF THEN DUMP THE BUFFER
JNZ FIND3
;LF FOUND
LDA PASS
ORA A
CNZ WOBUFF
LXI H, PBUFF ;CLEAR ERROR CHAR ON BOTH PASSES
MVI M, ' '
MVI A, 16
STA PBP ;START NEW LINE
FIND3:
MVI A, SPECL
;
STOKEN:
STA TOKEN
;
;
; LOOP WHILE CURRENT ITEM IS ACCUMULATING
SCTOK:
LDA NEXTC
STA LASTC ;SAVE LAST CHARACTER
ORA A
CNZ SAVER ;STORE CHARACTER INTO ACCUM IF NOT ZERO
CALL GNCN ;GET NEXT TO NEXTC
LDA TOKEN
CPI SPECL
RZ ;RETURN IF SPECIAL CHARACTER
CPI STRNG
CNZ TRANS ;TRANSLATE TO UPPER CASE IF NOT IN STRING
LXI H, NEXTC
LDA TOKEN
;
CPI IDEN
JNZ SCT2
;
;ACCUMULATING AN IDENTIFIER
CALL TDOLL ;$?
JZ SCTOK ;IF SO, SKIP IT
CALL ALNUM ;ALPHA NUMERIC?
RZ ;RETURN IF END
;NOT END OF THE IDENTIFIER
JMP SCTOK
;
SCT2: ;NOT SPECIAL OR IDENT, CHECK NUMBER
CPI NUMB
JNZ SCT3
;
;ACCUMULATING A NUMBER, CHECK FOR $
CALL TDOLL
JZ SCTOK ;SKIP IF FOUND
CALL HEX ;HEX CHARACTER?
JNZ SCTOK ;STORE IT IF FOUND
;END OF NUMBER, LOOK FOR RADIX INDICATOR
;
LDA NEXTC
CPI 'O' ;OCTAL INDICATOR
JZ NOCT
CPI 'O' ;OCTAL INDICATOR
JNZ NUM2
;
NOCT: ;OCTAL
MVI A, OCTV
JMP SSTYP
NUM2:
CPI 'H'
JNZ NUM3
MVI A, HEXV
SSTYP:
STA STYPE
XRA A
STA NEXTC ;CLEARS THE LOOKAHEAD CHARACTER
JMP NCON
;
; RADIX MUST COME FROM ACCUM
NUM3:
LDA LASTC
CPI 'B'
JNZ NUM4
MVI A, BINV
JMP SSTY1
;
NUM4:
CPI 'D'
MVI A, DECV
JNZ SSTY2
SSTY1:
LXI H, ACCLEN
DCR M ;ACCLEN DECREMENTED TO REMOVE RADIX INDICATOR
SSTY2:
STA STYPE
;
NCON: ;NUMERIC CONVERSION OCCURS HERE
LXI H, 0
SHLD VALUE ;VALUE ACCUMULATES BINARY EQUIVALENT
LXI H, ACCLEN
MOV C, M ;C=ACCLEN
INX H ;ADDRESSES ACCUM
CLOP: ;NEXT DIGIT IS PROCESSED HERE
MOV A, M
INX H ;READY FOR NEXT LOOP
CPI 'A'
JNC CLOP1 ;NOT HEX A-F
SUI '0' ;NORMALIZE
JMP CLOP2
;
CLOP1: ;HEX A-F H
SUI 'A'-10
CLOP2: ;CHECK SIZE AGAINST RADIX
PUSH H ;SAVE ACCUM ADDR
PUSH B ;SAVE CURRENT POSITION
MOV C, A
LXI H, STYPE
CMP M
CNC ERRV ;VALUE ERROR IF DIGIT>=RADIX
MVI B, 0 ;DOUBLE PRECISION DIGIT
MOV A, M ;RADIX TO ACCUMULATOR
LHLD VALUE
XCHG ;VALUE TO D,E - ACCUMULATE RESULT IN H,L
LXI H, 0 ;ZERO ACCUMULATOR
CLOP3: ;LOOP UNTIL RADIX GOES TO ZERO
ORA A
JZ CLOP4
RAR ;TEST LSB
JNC TTWO ;SKIP SUMMING OPERATION IF LSB=0
DAD D ;ADD IN VALUE
TTWO: ;MULTIPLY VALUE * 2 FOR SHL OPERATION
XCHG
DAD H
XCHG
JMP CLOP3
;
;
CLOP4: ;END OF NUMBER CONVERSION
DAD B ;DIGIT ADDED IN
SHLD VALUE
POP B
POP H
DCR C ;MORE DIGITS?
JNZ CLOP
RET ;DONE WITH THE NUMBER
;
SCT3: ;MUST BE A STRING
LDA NEXTC
CPI CR ;END OF LINE?
JZ ERRO ;AND RETURN
CPI
JNZ SCTOK
CALL GNCN
CPI ''''
RNZ ;RETURN IF SINGLE QUOTE ENCOUNTERED
JMP SCTOK ;OTHERWISE TREAT AS ONE QUOTE
;
; END OF SCANNER
;
; ERROR MESSAGE ROUTINES
ERRV: ;'V' VALUE ERROR
PUSH PSW
MVI A, 'V'
JMP ERR
;
ERRO: ;'O' OVERFLOW ERROR
PUSH PSW
MVI A, 'O'
JMP ERR
;
ERR: ;PRINT ERROR MESSAGE
PUSH B
PUSH H
CALL PERR
POP H
POP B
POP PSW
RET
;
ENDMOD:
EQU ($ AND 0FF00H) + 100H
END
; SYMBOL TABLE MANIPULATION MODULE
;
ORG 1340H
IOMOD EQU 200H ;IO MODULE ENTRY POINT
PCON EQU IOMOD+12H
EOR EQU IOMOD+1EH
;
;
; ENTRY POINTS TO SYMBOL TABLE MODULE
JMP ENDMOD
JMP INISY
JMP LOOKUP
JMP FOUND
JMP ENTER
JMP SETTY
JMP GETTY
JMP SETVAL
JMP GETVAL
;
; COMMON EQUATES
PBMAX EQU 120 ;MAX PRINT SIZE
PBUFF EQU 10CH ;PRINT BUFFER
PBP EQU PBUFF+PBMAX ;PRINT BUFFER POINTER
;
TOKEN EQU PBP+1 ;CURRENT TOKEN UDER SCAN
VALUE EQU TOKEN+1 ;VALUE OF NUMBER IN BINARY
ACCLEN EQU VALUE+2 ;ACCUMULATOR LENGTH
ACMAX EQU 64 ;MAX ACCUMULATOR LENGTH
ACCUM EQU ACCLEN+1
;
EVALUE EQU ACCUM+ACMAX ;VALUE FROM EXPRESSION ANALYSIS
;
SYTOP EQU EVALUE+2 ;CURRENT SYMBOL TOP
SYMAX EQU SYTOP+2 ;MAX ADDRESS+1
;
PASS EQU SYMAX+2 ;CURRENT PASS NUMBER
FPC EQU PASS+1 ;FILL ADDRESS FOR NEXT HEX BYTE
ASPC EQU FPC+2 ;ASSEMBLER'S PSEUDO PC
SYBAS EQU ASPC+2 ;BASE OF SYMBOL TABLE
SYADR EQU SYBAS+2 ;CURRENT SYMBOL BEING ACCESSED
;
; GLOBAL EQUATES
IDEN EQU 1 ;IDENTIFIER
NUMB EQU 2 ;NUMBER
STRNG EQU 3 ;STRING
SPECL EQU 4 ;SPECIAL CHARACTER
;
PLABT EQU 0001B ;PROGRAM LABEL
DLABT EQU 0010B ;DATA LABEL
EQUT EQU 0100B ;EQUATE
SETT EQU 0101B ;SET
MACT EQU 0110B ;MACRO
;
EXTT EQU 1000B ;EXTERNAL
REFT EQU 1011B ;REFER
GLBT EQU 1100B ;GLOBAL
;
CR EQU 0DH
; DATA AREAS
;SYMBOL TABLE BEGINS AT THE END OF THIS MODULE
FIXD EQU 5 ;5 BYTES OVERHEAD WITH EACH SYMBOL ENTRY
;2BY COLLISION, 1BY TYPE/LEN, 2BY VALUE
HSIZE EQU 128 ;HASH TABLE SIZE
HMASK EQU HSIZE-1 ;HASH MASK FOR CODING
HASHT:
DS HSIZE*2 ;HASH TABLE
HASHC:
DS 1 ;HASH CODE AFTER CALL ON LOOKUP
;
; SYMBOL TABLE ENTRY FORMAT IS
; -----------------
; : HIGH VAL BYTE :
; -----------------
; : LOW VAL BYTE :
; -----------------
; : CHARACTER H :
; -----------------
; : ... :
; ----------------- :
; : CHARACTER 1 :
; -----------------
; : TYPE ; LENG :
; -----------------
; : HIGH COLLISION:
; -----------------
; SYADR* : LOW COLLISION :
; -----------------
;
; WHERE THE LOW/HIGH COLLISION FIELD ADDRESSES ANOTHER ENTRY WITH
; THE SAME HASH CODE (OR ZERO IF THE END OF CHAIN), TYPE DESCRIBES
; THE ENTRY TYPE (GIVEN BELOW), LENG IS THE NUMBER OF CHARACTERS IN
; THE SYMBOL PRINTNAME -1 (I.E., LENG=0 IS A SINGLE CHARACTER PRINT-
; NAME, WHILE LENG=15 INDICATES A 16 CHARACTER NAME). CHARACTER 1
; THROUGH N GIVE THE PRINTNAME CHARACTERS IN ASCII UPPER CASE (ALL
; LOWER CASE NAMES ARE TRANSLATED ON INPUT), AND THE LOW/HIGH VALUE
; GIVE THE PARTICULAR ADDRESS OR CONSTANT VALUE ASSOCIATED WITH THE
; NAME. THE REPRESENTATION OF MACROS DIFFERS IN THE FIELDS WHICH
; FOLLOW THE VALUE FIELD (MACROS ARE NOT CURRENTLY IMPLEMENTED).
;
; THE TYPE FIELD CONSISTS OF FOUR BITS WHICH ARE ASSIGNED AS
; FOLLOWS:
;
; 0000 UNDEFINED SYMBOL
; 0001 LOCAL LABELLED PROGRAM
; 0010 LOCAL LABELLED DATA
; 0011 (UNUSED)
; 0100 EQUATE
; 0101 SET
; 0110 MACRO
; 0111 (UNUSED)
;
; 1000 (UNUSED)
; 1001 EXTERN LABELLED PROGRAM
; 1010 EXTERN LABELLED DATA
; 1011 REFERENCE TO MODULE
; 1100 (UNUSED)
; 1101 GLOBAL UNDEFINED SYMBOL
; 1110 GLOBAL LABELLED PROGRAM
; 1111 (UNUSED)
;
; TYPE DEFINITIONS
;
PLABT EQU 0001B ;PROGRAM LABEL
DLABT EQU 0010B ;DATA LABEL
EQUT EQU 0100B ;EQUATE
SETT EQU 0101B ;SET
MACT EQU 0110B ;MACRO
;
EXTT EQU 1000B ;EXTERNAL ATTRIBUTE
REFT EQU 1011B ;REFER
GLBT EQU 1100B ;GLOBAL ATTRIBUTE
;
;
INISY: ;INITIALIZE THE SYMBOL TABLE
LXI H, HASHT ;ZERO THE HASH TABLE
MVI B, HSIZE
XRA A ;CLEAR ACCUM
INIO:
MOV M, A
INX H
MOV M, A ;CLEAR DOUBLE WORD
INX H
DCR B
JNZ INIO
;SET SYMBOL TABLE POINTERS
LXI H, 0
SHLD SYADR
;
RET
;
CHASH: ;COMPUTE HASH CODE FOR CURRENT ACCUMULATOR
LXI H, ACCLEN
MOV B, M ;GET ACCUM LENGTH
XRA A ;CLEAR ACCUMULATOR
CH0:
INX H ;MOVE TO FIRST/NEXT CHARACTER POSITION
ADD M ;ADD WITH OVERFLOW
DCR B
JNZ CH0
ANI HMASK ;MASK BITS FOR MODULO HZISE
STA HASHC ;FILL HASHC WITH RESULT
RET
;
SETLN: ;SET THE LENGTH FIELD OF THE CURRENT SYMBOL
MOV B, A ;SAVE LENGTH IN B
LHLD SYADR
INX H
INX H
MOV A, M ;GET TYPE/LENGTH FIELD
ANI 0F0H ;MASK OUT TYPE FIELD
ORA B ;MASK IN LENGTH
MOV M, A
RET
;
GETLN: ;GET THE LENGTH FIELD TO REG-A
LHLD SYADR
INX H
INX H
MOV A, M
ANI 0FH
INR A ;LENGTH IS STORED AS VALUE - 1
RET
;
FOUND: ;FOUND RETURNS TRUE IF SYADR IS NOT ZERO (TRUE IS NZ FLAG HERE)
LHLD SYADR
MOV A, L
ORA H
RET
;
LOOKUP: ;LOOK FOR SYMBOL IN ACCUMULATOR
CALL CHASH ;COMPUTE HASH CODE
;NORMALIZE IDENTIFIER TO 16 CHARACTERS
LXI H, ACCLEN
MOV A, M
CPI 17
JC LENOK
MVI M, 16
LENOK:
;LOOK FOR SYMBOL THROUGH HASH TABLE
LXI H, HASHC
MOV E, M
MVI D, 0 ;DOUBLE HASH CODE IN D,E
LXI H, HASHT ;BASE OF HASH TABLE
DAD D
DAD D ;HASHT(HASHC)
MOV E, M ;LOW ORDER ADDRESS
INX H
MOV H, M
MOV L, E ;HEADER TO LIST OF SYMBOLS IS IN H,L
LOOK0:
SHLD SYADR
CALL FOUND
RZ ;RETURN IF SYADR BECOMES ZERO
;
;OTHERWISE EXAMINE CHARACTER STRING FOR MATCH
CALL GETLN ;GET LENGTH TO REG-A
LXI H, ACCLEN
CMP M
JNZ LCOMP
;
;LENGTH MATCH, TRY TO MATCH CHARACTERS
MOV B, A ;STRING LENGTH IN B
INX H ;HL ADDRESSES ACCUM
XCHG ;TO D,E
LHLD SYADR
INX H
INX H
INX H ;ADDRESSES CHARACTERS
LOOK1:
LDAX D ;NEXT CHARACTER FROM ACCUM
CMP M ;NEXT CHARACTER IN SYMBOL TABLE
JNZ LCOMP
;CHARACTER MATCHED, INCREMENT TO NEXT
INX D
INX H
DCR B
JNZ LOOK1
;
;COMPLETE MATCH AT CURRENT SYMBOL, SYADR IS SET
RET
;
LCOMP: ;NOT FOUND, MOVE SYADR DOWN ONE COLLISION ADDRESS
LHLD SYADR
MOV E, M
INX H
MOV D, M ;COLLISION ADDRESS IN D,E
XCHG
JMP LOOK0
;
;
ENTER: ;ENTER SYMBOL IN ACCUMULATOR
;ENSURE THERE IS ENOUGH SPACE IN THE TABLE
LXI H ;ACCLEN
MOV E, M
MVI D, 0 ;DOUBLE PRECISION ACCLEN IN D,E
LHLD SYTOP
SHLD SYADR ;NEXT SYMBOL LOCATION
DAD D ;SYTOP+ACCLEN
LXI D, FIXD ;FIXED DATA/SYMBOL
DAD D ;HL HAS NEXT TABLE LOCATION FOR SYMBOL
XCHG ;NEW SYTOP IN D,E
LHLD SYMAX ;MAXIMUM SYMTOP VALUE
MOV A, E
SUB L ;COMPUTE 16-BIT DIFFERENCE
MOV A, D
SBB H
XCHG ;NLW SYTOP IN H,L
JNC OVERER ;OVERFLOW IN TABLE
;
;OTHERWISE NO ERROR
SHLD SYTOP ;SET NEW TABLE TOP
LHLD SYADR ;SET COLLISION FIELD
XCHG ;CURRENT SYMBOL ADDRESS TO D,E
LXI H, HASHC ;HASH CODE FOR CURRENT SYMBOL TO H,L
MOV C, M ;LOW BYTE
MVI B, 0 ;DOUBLE PRECISION VALUE IN B,C
LXI H, HASHT ;BASE OF HASH TABLE
DAD B
DAD B ;HASHT(HASHC) IN H,L
;D,E ADDRESSES CURRENT SYMBOL - CHANGE LINKS
MOV C, M ;LOW ORDER OLD HEADER
INX H
MOV B, M ;HIGH ORDER OLD HEADER
MOV M, D ;HIGH ORDER NEW HEADER TO HASH TABLE
DCX H
MOV M, E ;LCW ORDER NEW HEADER TO HASH TABLE
XCHG ;H,L HOLDS SYMBOL TABLE ADDRESS
MOV M, C ;LOW ORDER OLD HEADER TO COLLISION FIELD
INX H
MOV M, B ;HIGH ORDER OLD HEADER TO COLLISION FIELD
;
;HASH CHAIN NOW REPAIRED FOR THIS ENTRY, COPY THE PRINTNAME
LXI D, ACCLEN
LDAX D ;GET SYMBOL LENGTH
CPI 17 ;LARGER THAN 16 SYMBOLS?
JC ENT1
MVI A, 16 ;TRUNCATE TO 16 CHARACTERS
;COPY LENGTH FIELD, FOLLOWED BY PRINTNAME CHARACTERS
ENT1:
MOV B, A ;COPY LENGTH TO B
DCR A ;1-16 CHANGED TO 0-15
INX H ;FOLLOWING COLLISION FIELD
MOV M, A ;STORE LENGTH WITH UNDEFINED TYPE (0000)
ENT2:
INX H
INX D
LDAX D
MOV M, A ;STORE NEXT CHARACTER OF PRINTNAME
DCR B ;LENGTH=LENGTH-1
JNZ ENT2 ;FOR ANOTHER CHARACTER
;
;PRINTNAME COPIED, ZERO THE VALUE FIELD
XRA A ;ZERO A
INX H ;LOW ORDER VALUE
MOV M, A
INX H
MOV M, A ;HIGH ORDER VALUE
RET
;
OVERER: ;OVERFLOW IN SYMBOL TABLE
LXI H, ERRO
CALL PCON
JMP EOR ;END OF EXEQUTION
ERRO:
DB 'SYMBOL TABLE OVERFLOW', CR
;
SETTY: ;SET CURRENT SYMBOL TYPE TO VALUE IN REG-A
RAL
RAL
RAL
RAL
ANI 0F0H ;TYPE MOVED TO HIGH ORDER 4-BITS
MOV B, A ;SAVE IT IN B
LHLD SYADR ;BASE OF SYMBOL TO ACCESS
INX H
INX H ;ADDRESS OF TYPE/LENGTH FIELD
MOV A, M ;GET IT AND MASK
ANI 0FH ;LEAVE LENGTH
ORA B ;MASK IN TYPE
MOV M, A ;STORE IT
RET
;
GETTY: ;RETURN THE TYPE OF THE VALUE IN CURRENT SYMBOL
LHLD SYADR
INX H
INX H
MOV A, M
RAR
RAR
RAR
RAR
ANI 0FH ;TYPE MOVED TO LOW 4-BITS OF REG-A
RET
;
VALADR: ;GET VALUE FIELD ADDRESS FOR CURRENT SYMBOL
CALL GETLN ;PRINTNAME LENGTH TO ACCUM
LHLD SYADR ;BASE ADDRESS
MOV E, A
MVI D, 0
DAD D ;BASE(LEN)
INX H
INX H ;FOR COLLISION FIELD
INX H ;FOR TYPE/LEN FIELD
RET ;WITH H,L ADDRESSING VALUE FIELD
;
SETVAL: ;SET THE VALUE FIELD OF THE CURRENT SYMBOL
;VALUE IS SENT IN H,L
PUSH H ;SAVE VALUE TO SET
CALL VALADR
POP D ;POP VALUE TO SET, HL HAS ADDRESS TO FILL
MOV M, E
INX H
MOV M, D ;FIELD SET
RET
;
GETVAL: ;GET THE VALUE FIELD OF THE CURRENT SYMBOL TO H,L
CALL VALADR ;ADDRESS OF VALUE FIELD TO H, L
MOV E, M
INX H
MOV D, M
XCHG
RET
;
ENDMOD EQU ($ AND 0FFE0H) + 20H
END
ORG 15A0H
JMP ENDMOD ;TO NEXT MODULE
JMP BSEAR
JMP BGET
;
; COMMON EQUATES
PBMAX EQU 120 ;MAX PRINT SIZE
PBUFF EQU 10CH ;PRINT BUFFER
PBP EQU PBUFF+PBMAX ;PRINT BUFFER POINTER
;
TOKEN EQU PBP+1 ;CURRENT TOKEN UDER SCAN
VALUE EQU TOKEN+1 ;VALUE OR NUMBER IN BINARY
ACCLEN EQU VALUE+2 ;ACCUMULATOR LENGTH
ACMAX EQU 64 ;MAX ACCUMULATOR LENGTH
ACCUM EQU ACCLEN+1
;
EVALUE EQU ACCUM+ACMAX ;VALUE FROM EXPRESSION ANALYSIS
;
SYTOP EQU EVALUE+2 ;CURRENT SYMBOL TOP
SYMAX EQU SYTOP+2 ;MAX ADDRESS+1
;
PASS EQU SYMAX+2 ;CURRENT PASS NUMBER
FPC EQU PASS+1 ;FILL ADDRESS FOR NEXT HEX BYTE
ASPC EQU FPC+2 ;ASSEMBLER'S PSEUDO PC
;
; GLOBAL EQUATES
IDEN EQU 1 ;IDENTIFIER
NUMB EQU 2 ;NUMBER
STRNG EQU 3 ;STRING
SPECL EQU 4 ;SPECIAL CHARACTER
;
PLABT EQU 0001B ;PROGRAM LABEL
DLABT EQU 0010B ;DATA LABEL
EQUT EQU 0100B ;EQUATE
SETT EQU 0101B ;SET
MACT EQU 0110B ;MACRO
;
EXTT EQU 1000B ;EXTERNAL
REFT EQU 1011B ;REFER
GLBT EQU 1100B ;GLOBAL
;
;
CR EQU 0DH ;CARRIAGB RETURN
;
;
; TABLE DEFINITIONS
;
; TYPES
XBASE EQU 0 ;START OF OPERATORS
; 01 THROUGH 015 DENOTE OPERATIONS
RT EQU 16
PT EQU RT+1 ;RT IS REGISTER TYPE, PT IS PSEUDO OPERATION
OBASE EQU PT+1
01 EQU OBASE+1 ;SIMPLE
02 EQU OBASE+2 ;LXI
03 EQU OBASE+3 ;DAD
04 EQU OBASE+4 ;PUSH/POP
05 EQU OBASE+5 ;JMP/CALL
06 EQU OBASE+6 ;MOV
07 EQU OBASE+7 ;MVI
08 EQU OBASE+8 ;ACC IMMEDIATE
09 EQU OBASE+9 ;LDAX/STAX
010 EQU OBASE+10 ;LHLD/SHLD/LDA/STA
011 EQU OBASE+11 ;ACCUM REGISTER
012 EQU OBASE+12 ;INC/DEC
013 EQU OBASE+13 ;INX/DCX
014 EQU OBASE+14 ;RST
015 EQU OBASE+15 ;IN/OUT
;
; X1 THROUGH X15 DENOTE OPERATORS
X1 EQU XBASE ;*
X2 EQU XBASE+1 ;/
X3 EQU XBASE+2 ;MOD
X4 EQU XBASE+3 ;SHL
X5 EQU XBASE+4 ;SHR
X6 EQU XBASE+5 ;+
X7 EQU XBASE+6 ;-
X8 EQU XBASF+7 ;UNARY -
X9 EQU XBASE+8 ;NOT
X10 EQU XBASF+9 ;AND
X11 EQU XBASE+10 ;OR
X12 EQU XBASE+11 ;XOR
X13 EQU XBASE+12 ;(
X14 EQU XBASE+13 ;)
X15 EQU XBASE+14 ;,
X16 EQU XBASE+15 ;CR
;
;
;
;
; RESERVED WORD TABLES
;
; BASE ADDRESS VECTOR FOR CHARACTERS
CINX:
DW CHAR1 ;LENGTH 1 BASE
DW CHAR2 ;LENGTH 2 BASE
DW CHAR3 ;LENGTH 3 BASE
DW CHAR4 ;LENGTH 4 BASE
DW CHARS ;LENGTH 5 BASE
DW CHAR6 ;LENGTH 6 BASE
;
CMAX EQU ($-CINX)/2-1 ;LARGEST STRING TO MATCH
;
CLEN: ;LENGTH VECTOR GIVES THE NUMBER OF ITEMS IN EACH TABLE
DB CHAR2-CHAR1
DB (CHAR3-CHAR2)/2
DB (CHAR4-CHAR3)/3
DB (CHAR5-CHAR4)/4
DB (CHAR6-CHAR5)/5
;
TVINX: ;TABLE OF TYPE,VALUE PAIRS FOR EACH RESERVED SYMBOL
DW TV1
DW TV2
DW TV3
DW TV4
DW TV5
;
; CHARACTER VECTORS FOR 1,2,3,4, AND 5 CHARACTER NAMES
CHAR1:
DB CR, '()*'
DB '+'
DB ', -/A'
DB 'BCDE'
DB 'HLM'
;
CHAR2:
DB 'DBDIDSDW'
DB 'EIIFINOR'
DB 'SP'
;
CHAR3:
DB 'ACIADCADDADI'
DB 'ANAANDANICMA'
DB 'CMCCMPCPIDAA'
DB 'DADDCRDCXEND'
DB 'EQUHLTINRINX'
DB 'JMPLDALXIMOD'
DB 'MOVMVINOPNOT'
DB 'ORACRGORIOUT'
DB 'POPPSWRALRAR'
DB 'RETRLCRRCRST'
DB 'SBBSBISETSHL'
DB 'SHRSTASTCSUB'
DB 'SUIXORXRAXRI'
;
CHAR4:
DB 'CALLENDMLDAXLHLDPCHL'
DB 'PUSHSHLDSPHLSTAX'
DB 'XCHGXTHL'
;
CHAR5:
DB 'ENDIFMACROTITLE'
;
CHAR6: ;END OF CHARACTER VECTOR
;
TV1: ;TYPE,VALUE PAIRS FOR CHAR1 VECTOR
DB X16, 10, X13, 20 ;CR (
DB X14, 30, X1, 80 ;)
DB X6, 70 ;+
DB X15, 10, X7, 70 ;, -
DB X2, 80, RT, 7 ;/ A
DB RT, 0, RT, 1 ;B C
DB RT, 2, RT, 3 ;D E
DB RT, 4, RT, 5 ;H L
DB RT, 6 ;M
;
TV2: ;TYPE,VALUE PAIRS FOR CHAR2 VECTOR
DB PT, 1, 01, 0F3H ;DB DI
DB PT, 2, PT, 3 ;DS DW
DB 01, 0FBH, PT, 8 ;EI IP
DB 015, 0DBH, X11, 40 ;IN OR
DB RT, 6 ;SP
;
;
TV3: ;TYPE,VALUE PAIRS FOR CHAR3 VECTOR
DB 08, 0CEH, 011, 88H ;ACI ADC
DB 011, 80H, 08, 0C6H ;ADD ADI
DB 011, 0A0H, X10, 50 ;ANA AND
DB 08, 0E6H, 01, 2FB ;ANI CMA
DB 01, 3FH, 011, 0B8H ;CMC CMP
DB 03, 0FEH, 01, 27H ;CPI DAA
DB 03, 09H, 012, 05H ;DAD DCR
DB 013, 0BH, PT, 4 ;DCX END
DB PT, 7, 01, 76H ;EQU HLT
DB 012, 04H, 013, 03H ;INR INX
DB 05, 0C3H, 010, 3AH ;JMP LDA
DB 02, 01H, X3, 80 ;LXI MOD
DB 06, 40H, 07, 06H ;MOV MVI
DB 01, 00H, X9, 60 ;NOP NOT
DB 011, 0B0H, PT, 10 ;ORA ORG
DB 08, 0F6H, 015, 0D3H ;ORI OUT
DB 04, 0C1H, RT, 6 ;POP PSW
DB 01, 17H, 01, 1FH ;RAL RAR
DB 01, 0C9H, 01, 07H ;PET RLC
DB 01, 0FH, 014, 0C7H ;RRC RST
DB 011, 098H, 03, 0DEH ;SSB SBI
DB PT, 11, X4, 80 ;SET SHL
DB X5, 80, 010, 32H ;STA STC
DB 01, 37H, 011, 90H ;STC SUB
DB 08, 0D6H, X12, 40 ;SUl XOR
DB 011, 0A8H, OS, 0EEH ;XRA XRI
;
;
TV4: ;TYPE,VALUE PAIRS FOR CHAR4 VECTOR
DB 05, 0CDH ;CALL
DB PT, 6, 09, 0AH ;ENDM LDAX
DB 010, 02AH, 01, 0E9H ;LHLD PCHL
DB 04, 0C5H, 010, 22H ;PUSH SHLD
DB 01, 0F9H, 09, 02H ;SPHL STAX
DB 01, 0EBH, 01, 0E3H ;XCHG XTHL
;
TV5: ;TYPE,VALUE PAIRS FOR CHAR5 VECTOR
DB PT, 5, PT, 9 ;ENDIF MACRO
DB PT, 12 ;TITLE
;
SUFTAS: ;TABLE OF SUFFIXES FOR J C AND R OPERATIONS
DB 'NZZ NCC POPEP M'
;
BSEAR: ;BINARY SEARCH MNEMONIC TABLE
; INPUT: UR = UPPER BOUND OF TABLE (I.E., TABLE LENGTH-1)
; SR = SIZE OF EACH TABLE ELEMENT
; H,L ADDRESS BASE OF TABLE TO SEARCH
; OUTPUT: ZERO FLAG INDICATES MATCH WAS FOUND, IN WHICH CASE
; THE ACCUMULATOR CONTAINS AN INDEX TO THE ELEMENT
; NOT ZERO FLAG INDICATES NO MATCH FOUND IN TABLE
;
UR EQU B ;UPPER SOUND REGISTER
LR EQU C ;LOWER BOUND REGISTER
SR EQU D ;SIZE REGISTER
MR EQU E ;MIDDLE POINTER REGISTER
SP1 EQU B ;SIZE PRIME, USED IN COMPUTING MIDDLE FOSITON
SP1P EQU C ;ANOTHER COPY OF SIZE PRIME
KR EQU H ;K
;
MVI MR, 255 ;MARK M <> OLD M
INR UR ;U=U+1
MVI LR, 0 ;L = 0
;
; COMPUTE M' = (U+L)/2
NEXT:
XRA A
MOV A, UR ;CY=0, A=U
ADD LR ;(U+L)
RAR ;(U+L)/2
CMP MR ;SAME AS LAST TIME THROUGH?
JZ NMATCH ;JUMP IF = TO NO MATCH
;
;MORE ELEMENTS TO SCAN
MOV MR, A ;NEW MIDDLE VALUE
PUSH H ;SAVE A COPY OF THE BASE ADDRESS
PUSH D ;SAVE S,M
PUSH B ;SAVE U,L
PUSH H ;SAVE ANOTHER COPY OF THE BASE ADDRESS
MOV SP1, SR ;S'= S
MOV SP1P, SP1 ;S** = S*
DCR A ;ACCLEN-1
MOV E, A
MVI D, 0 ;DOUBLE ACCLEN-1 TO D,E
PUSH D ;SAVE A COPY FOR LATER
CPI CMAX ;TOO LONG?
JNC NGET ;NOT IN RANGE IF CARRY
LXI H, CLEN ;LENGTH VECTOR
DAD D
MOV UR, M ;FILL UPPER BOUND FROM MEMORY
LXI H, CINX
DAD D
DAD D ;BASE ADDRESS TO H,L
MOV D, M
INX H
MOV H, M
MOV L, D ;NOW IN H,L
MOV SR, C ;FILL THE SIZE REGISTER
CALL BSEAR ;PERFORM THE BINARY SEARCH
JNZ SCASE ;ZERO IF FOUND
POP D ;RESTORE INDEX
LXI H, TVINX
DAD D
DAD D ;ADDRESSING PROPER TV ELEMENT
MOV E, M
INX H
MOV D, M
;D,E IS BASE ADDRESS OF TYPE/VALUE VECTOR, ADD DISPLACEMENT
MOV L, A
MVI H, 0
DAD H ;DOUBLED
DAD D ;INDEXED
MOV A, M ;TYPE TO ACC
INX H
MOV B, M ;VALUE TO B
RET ;TYPE IN ACC, VALUE IN B
;
SCASE: ;NAME NOT TOO LONG, BUT NOT FOUND IN TABLES, MAY BE J C OR R
POP D ;RESTORE INDEX
CALL PREFIX
RNZ ;NOT FOUND AS PREFIX J C OR R IF NOT ZERO FLAG
PUSH B ;SAVE VALUE AND TYPE
CALL SUFFIX ;ZERO IF SUFFIX MATCHED
MOV A, B ;READY FOR MASK IF ZERO FLAG
POP B ;RECALL VALUE AND TYPE
RNZ ;RETURN IF NOT ZERO FLAG SET
;MASK IN THE PROPER BITS AND RETURN
ORA A ;CLEAR CARRY
RAL
RAL
RAL
ORA B ;VALUE SET TO JNZ ...
MOV B, A ;REPLACE
MOV A, C ;RETURN WITH TYPE IN REGISTER A
CMP A ;CLEAR THE ZERO FLAG
RET
;
NGET: ;CAN'T FIND THE ENTRY, RETURN WITH ZERO FLAG RESET
POP D ;GET THE ELEMENT BACK
XRA A ;CLEAR
INR A ;ZERO FLAG RESET
RET
;
;
ENDMOD EQU ($ AND 0FFE0H) + 20H ;NEXT MODULE ADDRESS
END
DCR A ;ACCLEN-l
MOV E, A
MVI D, 0 ;DOUBLE ACCLEN-1 TO D,E
PUSH D ;SAVE A COPY FOR LATER
CPI CMAX ;TOO LONG?
JNC NGET ;NOT IN RANGE IF CARRY
LXI H, CLEN ;LENGTH VECTOR
DAD D
MOV UR, M ;FILL UPPER BOUND FROM MEMORY
LXI H, CINX
DAD D
DAD D ;BASE ADDRESS TO H,L
MOV D, M
INX H
MOV H, M
MOV L, D ;NOW IN H,L
MOV SR, C ;FILL THE SIZE REGISTER
CALL BSEAR ;PERFORM THE BINARY SEARCH
JNZ SCASE ;ZERO IF FOUND
POP D ;RESTORE INDEX
LXI H, TVINX
DAD D
DAD D ;ADDRESSING PROPER TV ELEMENT
MOV E, M
INX H
MOV D, M
;D,E IS BASE ADDRESS OF TYPE/VALUE VECTOR, ADD DISPLACEMENT
MOV L, A
MVI H, 0
DAD H ;DOUBLED
DAD D ;INDEXED
MOV A, M ;TYPE TO ACC
INX H
MOV B, H ;VALUE TO B
RET ;TYPE IN ACC, VALUE IN B
;
SCASE: ;NAME NOT TOO LONG, BUT NOT FOUND IN TABLES, MAY BE J C OR R
POP D ;RESTORE INDEX
CALL PREFIX
RNZ ;NOT FOUND AS PREFIX J C OR R IF NOT ZERO FLAG
PUSH B ;SAVE VALUE AND TYPE
CALL SUFFIX ;ZERO IF SUFFIX MATCHED
MOV A, B ;READY FOR MASK IF ZERO FLAG
POP B ;RECALL VALUE AND TYPE
RNZ ;RETURN IF NOT ZERO FLAG SET
;MASK IN THE PROPER BITS AND RETURN
ORA A ;CLEAR CARRY
RAL
RAL
RAL
ORA B ;VALUE SET TO JNZ ...
MOV B, A ;REPLACE
MOV A, C ;RETURN WITH TYPE IN REGISTER A
CMP A ;CLEAR THE ZERO FLAG
RET
;
NGET: ;CAN'T FIND THE ENTRY, RETURN WITH ZERO FLAG RESET
POP D ;GET THE ELEMENT BACK
XRA A ;CLEAR
INR A ;ZERO FLAG RESET
RET
;
;
ENDMOD EQU ($ AND 0FFE0H) + 20H ;NEXT MODULE ADDRESS
END
;OPERAND SCAN MODULE
ORG 1860H
;
; EXTERNALS
IOMOD EQU 200H ;I/O MODULE
SCMOD EQU 1100H ;SCANNER MODULE
SYMOD EQU 1340H ;SYMBOL TABLE MODULE
BMOD EQU 15A0H ;BINARY SEARCH MODULE
;
;
PERR EQU IOMOD+18H
SCAN EQU SCMOD+6H ;SCANNER ENTRY POINT
CR EQU 0DH ;CARRIAGE RETURN
;
LOOKUP EQU SYMOD+6H ;LOOKUP
FOUND EQU LOOKUP+3 ;FOUND SYMBOL IF ZERO FLAG NOT SET
ENTER EQU FOUND+3 ;ENTER SYMBOL
SETTY EQU ENTER+3 ;SET TYPE FIELD
GETTY EQU SETTY+3 ;SET TYPE FIELD
SETVAL EQU GETTY+3 ;SET VALUE FIELD
GETVAL EQU SETVAL+3 ;GET VALUE FIELD
;
BSEAR EQU BMOD+3 ;BINARY SEARCH ROUTINE
BGET EQU BSEAR+3 ;GET VALUES WITH SEARCH
;
; COMMON EQUATES
PBMAX EQU 120 ;MAX PRINT SIZE
PBUFF EQU 10CH ;PRINT BUFFER
PBP EQU PBUFF+PBMAX ;PRINT BUFFER POINTER
;
TOKEN EQU PBP+1 ;CURRENT TOKEN UDER SCAN
VALUE EQU TOKEN+1 ;VALUE OF NUMBER IN BINARY
ACCLEN EQU VALUE+2 ;ACCUMULATOR LENGTH
ACMAX EQU 64 ;MAX ACCUMULATOR LENGTH
ACCUM EQU ACCLEN+1
;
EVALUE EQU ACCUM+ACMAX ;VALUE FROM EXPRESSION ANALYSIS
;
SYTOP EQU EVALUE+2 ;CURRENT SYMBOL TOP
SYMAX EQU SYTOP+2 ;MAX ADDRESS+1
;
PASS EQU SYMAX+2 ;CURRENT PASS NUMBER
FPC EQU PASS+1 ;FILL ADDRESS FOR NEXT HEX BYTE
ASPC EQU PPC+2 ;ASSEMBLER'S PSEUDO PC
;
; GLOBAL EQUATES
IDEN EQU 1 ;IDENTIFIER
NUMB EQU 2 ;NUMBER
STRNG EQU 3 ;STRING
SPECL EQU 4 ;SPECIAL CHARACTER
;
PLABT EQU 0001B ;PROGRAM LABEL
DLABT EQU 0010B ;DATA LABEL
EQUT EQU 0100B ;EQUATE
SETT EQU 0101B ;SET
MACT EQU 0110B ;MACRO
;
EXTT EQU 1000B ;EXTERNAL
REFT EQU 1011B ;REFER
GLBT EQU 1100B ;GLOBAL
;
;
; TABLE DEFINITIONS
XBASE EQU 0 ;START OF OPERATORS
OPER EQU 15 ;LAST OPERATOR
RT EQU 16
PT EQU RT+1 ;RT IS REGISTER TYPE, PT IS PSEUDO OPERATION
OBASE EQU PT+1
;
PLUS EQU 5
MINUS EQU 6
NOTF EQU 8 ;NOT
LPAR EQU 12
RPAR EQU 13
OSMAX EQU 10
VSMAX EQU 8*2
;
;
; BEGINNING OF MODULE
JMP ENDMOD ;PAST THIS MODULE
JMP OPAND ;SCAN OPERAND FIELD
JMP MULF ;MULTIPLY FUNCTION
JMP DIVE ;DIVIDE FUNCTION
UNARY:
DS 1 ;TRUE IF NEXT OPERATOR IS UNARY
OPERV:
DS OSMAX ;OPERATOR STACK
HIERV:
DS OSMAX ;OPERATOR PRIORITY
VSTACK:
DS VSMAX ;VALUE STACK
OSP:
DS 1 ;OPERATOR STACK POINTER
VSP:
DS 1 ;VALUE STACK POINTER
;
;
;
STKV: ;PLACE CURRENT H,L VALUE AT TOP OF VSTACK
XCHG ;HOLD VALUE IN D,E
LXI H, VSP
MOV A, M
CPI VSMAX
JC STKV0
CALL ERREX ;OVERFLOW IN EXPRESSION
MVI M, 0 ;VSP=0
STKV0:
MOV A, M ;GET VSP
INR M ;VSP=VSP+1
INR M ;VSP=VSP+2
MOV C, A ;SAVE VSP
MVI B, 0 ;DOUBLE VSP
LXI H, VSTACK
DAD B
MOV M, E ;LOW BYTE
INX H
MOV M, D ;HIGH BYTE
RET
;
STKO: ;STACK OPERATOR (REG-A) AND PRIORITY (REG-B)
PUSH PSW ;SAVE IT
LXI H, OSP
MOV A, M
CPI OSMAX
JC STK01
MVI M, 0
CALL ERREX ;OPERATOR STACK OVERFLOW
STK01:
MOV E, M ;GET OSP
MVI D, 0
INR M ;OSP=OSP+1
POP PSW ;RECALL OPERATOR
LXI H, OPERV
DAD D ;OPERV(OSP)
MOV M, A ;OPERV(OSP)=OPERATOR
LXI H, HIERV
DAD D
MOV M, B ;HIERV(OSP)=PRIORITY
RET
;
LODV1: ;LOAD TOP ELEMENT FROM VSTACK TO H,L
LXI H, VSP
MOV A, M
ORA A
JNZ LODOK
CALL ERREX ;UNDERFLOW
LXI H, 0
RET
;
LODOK:
DCR M
DCR M ;VSP=VSP-2
MOV C, M ;LOW BYTE
MVI B, 0
LXI H, VSTACK
DAD B ;VSTACK(VSP)
MOV C, M ;GET LOW BYTE
INX H
MOV H, M
MOV L, C
RET
;
LODV2: ;LOAD TOP TWO ELEMENTS DE HOLDS TOP, HL HOLDS TOP-1
CALL LODV1
XCHG
CALL LODV1
RET
;
APPLY: ;APPLY OPERATOR IN REG-A TO TOP OF STACK
MOV L, A
MVI H, 0
DAD H ;OPERATOR NUMBER*2
LXI D, OPTAB
DAD D ;INDEXED OPTAB
MOV E, M ;LOW ADDRESS
INX H
MOV H, M ;HIGH ADDRESS
MOV L, E
PCHL ;SET PC AND GO TO SUBROUTINE
;
OPTAB:
DW MULOP
DW DIVOP
DW MODOP
DW SHLOP
DW SHROP
DW ADDOP
DW SUBOP
DW NEGOP
DW NOTOP
DW ANDOP
DW OROP
DW XOROP
DW ERREX ;(
;
; SPECIFIC HANDLERS FOLLOW
SHFT: ;SET UP OPERANDS FOR SHIFT L AND R
CALL LODV2
MOV A, D ;ENSURE 0-15
ORA A
JNZ SHERR
MOV A, E
CPI 17
RC ;RETURN IP 0-16 SHIFT
SHERR:
CALL ERREX
MVI A, 16
RET
;
NEGF: ;COMPUTE 0-H,L TO H,L
XRA A
SUB L
MOV L, A
MVI A, 0
SBB H
MOV H, A
RET
;
DIVF:
CALL LODV2
DIVE: ;(EXTERNAL ENTRY FROM MAIN PROGRAM)
XCHG ;SWAP D,E WITH H,L FOR DIVIDE FUNCTION
;COMPUTE X/Y WHERE X IS IN D,E AND Y IS IN H,L
;THE VALUE OF X/Y APPEARS IN D,E AND X MOD Y IS IN H,L
;
SHLD DTEMP ;SAVE X IN TEMPORARY
LXI H, BNUM ;STORE BIT COUNT
MVI M, 11H
LXI B, 0 ;INTIALIZE RESULT
PUSH B
XRA A ;CLEAR FLAGS
DLOOP:
MOV A, E ;GET LOW Y BYTE
RAL
MOV E, A
MOV A, D
RAL
MOV D, A
DCR M ;DECREMENT BIT COUNT
POP H ;RESTORE TEMP RESULT
RZ ;ZERO BIT COUNT MEANS ALL DONE
MVI A, 0 ;ADD IN CARRY
ACI 0 ;CARRY
DAD H ;SHIFT TEMP RESULT LEFT ONE BIT
MOV B, H ;COPY HA AND L TO A A ND C
ADD L
LHLD DTEMP ;GET ADDRESS OF X
SUB L ;SUBTRACT FROM TEMPORARY RESULT
MOV C, A
MOV A, B
SBB H
MOV B, A
PUSH B ;SAVE TEMP RESULT IN STACK
JNC DSKIP ;NO BORROW FROM SUBTRACT
DAD B ;ADD X BACK IN
XTHL ;REPLACE TEMP RESULT ON STACK
DSKIP:
LXI H, BNUM ;RESTORE H,L
CMC
JMP DLOOP ;REPEAT LOOP STEPS
;
DTEMP:
DS 2
BNUM:
DS 1
;
MULF: ;MULTIPLY D,E BY H,L AND REPLACE H,L WITH RESULT
MOV B, H
MOV C, L ;COPY OF 1ST VALUE TO B,C FOR SHIFT AND ADD
LXI H, 0 ;H,L IS THE ACCUMULATOR
MUL0:
XRA A
MOV A, B ;CARRY IS CLEARED
RAR
MOV B, A
MOV A, C
RAR
MOV C, A
JC MUL1 ;SKIP THIS ADD IF LSB IS ZERO
ORA B
RZ ;RETURN WITH H,L
JMP MUL2 ;SKIP ADD
MUL1:
DAD D ;ADD CURRENT VALUE OF D
MUL2:
XCHG ;READY FOR *2
DAD H
XCHG
JMP MUL0
;
MULOP: ;MULTIPLY D,E BY H,L
CALL LODV2
CALL MULF
JMP ENDOP
;
DIVOP: ;DIVIDE H,L BY D,E
CALL DIVF
XCHG ;RESULT TO H,L
JMP ENDOP
;
MODOP:
CALL DIVF
JMP ENDOP
;
SHLOP:
CALL SHFT ;CHECK VALUES
SHL0:
ORA A ;DONE?
JZ ENDOP
DAD H ;HL=HL*2
DCR A
JMP SHL0
;
SHROP:
CALL SHFT
SHR0:
ORA A ;DONE?
JZ ENDOP
PUSH PSW ;SAVE CURRENT COUNT
XRA A
MOV A, H
RAR
MOV H, A
MOV A, L
RAR
MOV L, A
POP PSW
DCR A
JMP SHR0
;
ADDOP:
CALL LODV2
ADD0:
DAD D
JMP ENDOP
;
SUBOP:
CALL LODV2
XCHG ;TREAT AS HL+(-DE)
CALL NEGF ;0-HL
JMP ADD0
;
NEGOP:
CALL LODV1
NEG0:
CALL NEGF ;COMPUTE 0-HL
JMP ENDOP
;
NOTOP:
CALL LODV1
INX H ;65536-HL - 65535-(HL+1)
JMP NEG0
;
ANDOP:
CALL LODV2
MOV A, D
ANA H
MOV H, A
MOV A, E
ANA L
MOV L, A
JMP ENDOP
;
OROP:
CALL LODV2
MOV A, D
ORA H
MOV H, A
MOV A, E
ORA L
MOV L, A
JMP ENDOP
;
XOROP:
CALL LODV2
MOV A, D
XRA H
MOV H, A
MOV A, E
XRA L
MOV L, A
;
ENDOP:
JMP STKV
;
;
;
ENDEXP: ;RETURNS ZERO FLAG IF SYMBOL IS CR, :, OR .
LDA TOKEN
CPI SPECL
RNZ ;NOT END IF NOT SPECIAL
;
LDA ACCUM
CPI CR
RZ
CPI ';'
RZ
CPI ','
RZ
CPI '|'
RET
;
OPAND: ;SCAN THE OPERAND FIELD OF AN INSTRUCTION
; (NOT A DB WITH FIRST TOKEN STRING > 2 OR 0)
XRA A
STA OSP ;ZERO OPERATOR STACK POINTER
STA VSP
DCR A ;255
STA UNARY
LXI H, 0
SHLD EVALUE
;
OP0: ;ARRIVE HERE WITH NEXT ITEM ALREADY SCANNED
CALL ENDEXP ;DONE?
JNZ OP1
;EMPTY THE OPERATOR STACK
EMPOP:
LXI H, OSP
MOV A, M ;GET THE OSP AND CHECK FOR EMPTY
ORA A
JZ CHKVAL ;JUMP IF EMPTY
DCR M ;POP ELEMENT
MOV E, A ;COPY FOR DOUBLE ADD
DCR E
MVI D, 0
LXI H, OPERV
DAD D ;INDEXED - OPERV(OSP)
MOV A, M ;GET OPERATOR
CALL APPLY ;APPLY OPERATOR
JMP EMPOP
;
CHKVAL:
LDA VSP ;MUST HAVE ONE ELEMENT IT THE STACK
CPI 2
CNZ ERREX
LDA PBUFF
CPI ' '
RNZ ;EVALUE REMAINS AT ZERO
LHLD VSTACK ;GET DOUBLE BYTE IN STACK
SHLD EVALUE
RET
;
OP1: ;MORE TO SCAN
LDA PBUFF
CPI ' '
JNZ GETOP
LDA TOKEN
CPI STRNG ;IS THIS A STRING?
JNZ OP3
;
;STRING - CONVERT TO DOUBLE PRECISION
LDA ACCLEN
ORA A
CZ ERREX ;ERROR IF LENGTH=0
CPI 3
CNC ERREX ;ERROR IF LENGTH>2
MVI D, 0
LXI H, ACCUM
MOV E, M ;LSBYTE
INX H
DCR A ;A HAS THE LENGTH
JZ OP2 ;ONE OR TWO BYTES
MOV D, M ;FILL HIGH ORDER
OP2:
XCHG ;VALUE TO H,L
JMP STNUM ;STORE TO STACK
;
OP3: ;NOT A STRING, CHECK FOR NUMBER
CPI NUMB
JNZ OP4
LHLD VALUE ;NUMERIC VALUE
JMP STNUM
;
OP4: ;NOT STRING OR NUMBER, MUST BE ID OR SPECL
CALL BGET ;BINARY SEARCH, GET ATTRIBUTES
JNZ OP6 ;MATCH?
;YES, MAY BE OPERATOR
CPI OPER+1
JNC OP5
;OPERATOR ENCOUNTERED MS NIBBLE OF B IS PRIORITY NUMBER LS NIBBLE
;IS THE OPERATOR
;ACC HAS THE OPERATOR NUMBER, B HAS PRIORITY
CPI LPAR ;(?
MOV C, A ;SAVE COPY OF OPERATOR NUMBER
LDA UNARY
JNZ OPER1 ;JUMP IF NOT A (
; ( ENCOUNTERED, UNARY MUST BE TRUE
ORA A
CZ ERREX
MVI A, 0FFH
STA UNARY ;UNARY IS SET TRUE
MOV A, C ;RECOVER OPERATOR
JMP OPER4 ;CALLS STKO AND SETS UNARY TO TRUE
;
;
OPER1: ;NOT A LEFT PAREN
ORA A
JNZ OPER6 ;MUST BE + OR - SINCE UNARY IS SET
;
;UNARY NOT SET, MUST BE BINARY OPERATOR
OPER2: ;COMPARE HIERARCHY OF TOS
PUSH B ;SAVE PRIORITY AND OPERATOR NUMBER
LDA OSP
ORA A
JZ OPER3 ;NO MORE OPERATORS IN STACK
MOV E, A ;OSP TO E
DCR E ;OSP-1
MVI D, 0
LXI H, HIERV
DAD D ;HL ADDRESSES TOP OF OPERATOR STACK
MOV A, M ;PRIORITY OF TOP OPERATOR
CMP B ;CURRENT GREATER?
JC OPER3 ;JUMP IF SO
;APPLY TOP OPERATOR TO VALUE STACK
LXI H, OSP
MOV M, E ;OSP-OSP-1
LXI H, OPERV
DAD D
MOV A, M ;OPERATOR NUMBER TO ACC
CALL APPLY
POP B ;RESTORE OPERATOR NUMBER AND PRIORITY
JMP OPER2 ;FOR ANOTHER TEST
;
OPER3: ;ARRIVE HERE WHEN OPERATOR IS STACKED
;CHECK FOR RIGHT PAREN BALANCE
POP B ;OPERATOR NUMBER IN C, PRIORITY IN B
MOV A, C
CPI RPAR
JNZ OPER4 ;JUMP IF NOT A RIGHT PAREN
;
;RIGHT PAREN FOUND, STACK MUST CONTAIN LEFT PAREN TO DELETE
LXI H, OSP
MOV A, M
ORA A ;ZERO?
JZ LPERR ;PAREN ERROR IF SO
DCR A ;OSP-1
MOV M, A ;STORED TO MEMORY
MOV E, A
MVI D, 0
LXI H, OPERV
DAD D
MOV A, M ;TOP OPERATOR IN REG-A
CPI LPAR
JZ NLERR ;JMP IF NO ERROR - PARENS BALANCE
LPERR:
CALL ERREX
NLERR: ;ERROR REPORTING COMPLETE
XRA A
JMP OPER5 ;TO CLEAR UNARY FLAG
;
OPER4: ;ORDINARY OPERATOR
CALL STKO
MVI A, 0FFH ;TO SET UNARY FLAG
OPER5:
STA UNARY
JMP GETOP ;FOP ANOTHER ELEMENT
;
OPER6: ;UNARY SET, MUST BE + OR -
MOV A, C ;RECALL OPERATOR
CPI PLUS
JZ GETOP ;IGNORE UNARY PLUS
CPI MINUS
JNZ CHKNOT
INR A ;CHANGE TO UNARY MINUS
MOV C, A
JMP OPER2
CHKNOT: ;UNARY NOT SYMBOL?
CPI NOTF
CNZ ERREX
JMP OPER2
;
OP5: ;ELEMENT FOUND IN TABLE, NOT AN OPERATOR
CPI PT ;PSEUDO OPERATOR?
CZ ERREX ;ERROR IF SO
MOV L, B ;GET LOW VALUE TO L
MVI H, 0 ;ZERO HIGH ORDER BYTE
JMP STNUM ;STORE IT
;
OP6: ;NOT POUND IN TABLE SCAN, $?
LDA TOKEN
CPI SPECL
JNZ OP7
LDA ACCUM
CPI '$'
JZ CURPC ;USE CURRENT PC
CALL ERREX
LXI H, 0
JMP STNUM
CURPC:
LHLD ASPC ;GET CURRENT PC
JMP STNUM
:
0P7: ;NOT $, LOOK IT UP
CALL LOOKUP
CALL FOUND
JNZ FIDENT
;NOT FOUND IN SYMBOL TABLE, ENTER IF PASS 1
MVI A, 'P'
CALL PERR
CALL ENTER ;ENTER SYMBOL WITH ZERO TYPE FIELD
JMP FIDE0
FIDENT:
CALL GETTY ;TYPE TO H,L
ANI 111B
MVI A, 'U'
CZ PERR
;
FIDE0:
CALL GETVAL ;VALUE TO H,L
;
STNUM: ;STORE H,L TO VALUE STACK
LDA UNARY
ORA A ;UNARY OPERATION SET
XRA ARREX ;OPERAND ENCOUNTERED WITH UNARY OFF
STA UNARY ;SET TO OFF
CALL STKV ;STACK THE VALUE
;
GETOP:
CALL SCAN
JMP OP0
;
ERREX: ;PUT 'E' ERROR IN OUTPUT BUFFER
PUSH H
MVI A, 'E'
CALL PERR
POP H
RET
;
ENDMOD EQU ($ AND 0FFE0H) + 20H ;NEXT HALF PAGE
END
; CP/M RESIDENT ASSEMBLER MAIN PROGRAM
; COPYRIGHT (C) 1976
; GARY A. KILDALL
;
ORG 1BA0H
; MODULE ENTRY POINTS
IOMOD EQU 200H ;IO MODULE
SCMOD EQU 1100H ;SCANNER MODULE
SYMOD EQU 1340H ;SYMBOL TABLE MODULE
BMOD EQU 15A0H ;BINARY SEARCH MODULE
OPMOD EQU 1860H ;OPERAND SCAN MODULE
;
SETUP EQU IOMOD+3H ;FILE SETUP FOR EACH PASS
PCON EQU IOMOD+12H ;WRITE CONSOLE BUFFER TO CR
WOBUFF EQU IOMOD+15H ;WRITE PRINT BUFFER AND REINITIALIZE
PERR EQU IOMOD+18H ;WRITE ERROR CHARACTER TO PRINT BUFFER
DHEX EQU IOMOD+1BH ;SEND HEX CHARACTER TO MACHINE CODE FILE
EOR EQU IOMOD+1EH ;END OF PROCESSING, CLOSE FILES AND TERMINATE
;
INITS EQU SCMOD+3H ;INITIALIZE SCANNER MODULE
SCAN EQU SCMOD+6H ;SCAN NEXT TOKEN
;
INISY EQU SYMOD+3H ;INITIALIZE SYMBOL TABLE
LOOKUP EQU SYMOD+6H ;LOOKUP SYMBOL IN ACCUMULATOR
FOUND EQU SYMOD+9H ;FOUND IF NZ FLAG
ENTER EQU SYMOD+0CH ;ENTER SYMBOL IN ACCUMULATOR
SETTY EQU SYMOD+0FH ;SET TYPE FIELD
GETTY EQU SYMOD+12H ;GET TYPE FIELD
SETVAL EQU SYMOD+15H ;SET VALUE FIELD
GETVAL EQU SYMOD+18H ;GET VALUE FIELD
;
BGET EQU BMOD+6H ;BINARY SEARCH AND GET TYPE/VALUE PAIR
;
OPAND EQU OPMOD+3H ;GET OPERAND VALUE TO 'EVALUE'
MULF EQU OPMOD+6H ;MULT D,E BY H,L TO H,L
DIVF EQU OPMOD+9H ;DIVIDE HL BY DE, RESULT TO DE
;
;
; COMMON EQUATES
PBMAX EQU 120 ;MAX PRINT SIZE
PBUFF EQU 10CH ;PRINT BUFFER
PBP EQU PBUFF+PBMAX ;PRINT BUFFER POINTER
;
TOKEN EQU PBP+1 ;CURRENT TOKEN UDER SCAN
VALUE EQU TOKEN+1 ;VALUE OF NUMBER IN BINARY
ACCLEN EQU VALUE+2 ;ACCUMULATOR LENGTH
ACMAX EQU 64 ;MAX ACCUMULATOR LENGTH
ACCUM EQU ACCLEN+1
;
EVALUE EQU ACCUM+ACMAX ;VALUE FROM EXPRESSION ANALYSIS
;
SYTOP EQU EVALUE+2 ;CURRENT SYMBOL TOP
SYMAX EQU SYTOP+2 ;MAX ADDRESS+1
;
PASS EQU SYMAX+2 ;CURRENT PASS NUMBER
FPC EQU PASS+1 ;FILL ADDRESS FOR NEXT HEX BYTE
ASPC EQU FPC+2 ;ASSEMBLER'S PSEUDO PC
SVBAS EQU ASPC+2 ;BASE OF SYMBOL TABLE
SYADR EQU SYBAS+2 ;CURRENT SYMBOL ADDRESS
;
; GLOBAL EQUATES
IDEN EQU 1 ;IDENTIFIER
NUMB EQU 2 ;NUMBER
STRNG EQU 3 ;STRING
SPECL EQU 4 ;SPECIAL CHARACTER
;
PLABT EQU 0001B ;PROGRAM LABEL
DLABT EQU 0010B ;DATA LABEL
EQUT EQU 0100B ;EQUATE
SETT EQU 0101B ;SET
MACT EQU 0110B ;MACRO
;
EXTT EQU 1000B ;EXTERNAL
REFT EQU 1011B ;REFER
GLBT EQU 1100B ;GLOBAL
;
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
EOF EQU 1AH ;END OF FILE
NBMAX EQU 16 ;STARTING POSITION OF PRINT LINE
;
;
RT EQU 16 ;REGISTER TYPE
PT EQU RT+1 ;PSEUDO OPERATION
PENDIF EQU 5 ;PSEUDO OPERATOR 'ENDIF'
OBASE EQU PT+1
O1 EQU OBASE+1 ;FIRST OPERATOR
O15 EQU OBASE+15 ;LAST OPERATOR
;
; MAIN STATEMENT PROCESSING LOOP
XRA A
STA PASS ;SET TO PASS 0 INITIALLY
CALL INISY ;INITIALIZE THE SYMBOL TABLE
RESTART: ;PASS LOOP GOES FROM 0 TO 1
CALL INITS ;INITIALIZE THE SCANNER
CALL SETUP ;SET UP THE INPUT FILE
LXI H, 0
SHLD SYLAB ;ASSUME NO STARTING LABEL
SHLD FPC
SHLD ASPC
SHLD EPC ;END PC
;
SCNEXT: ;SCAN THE NEXT INPUT ITEM
CALL SCAN
SCN0:
LDA TOKEN
CPI NUMB ;SKIP LEADING NUMBERS FROM LINE EDITORS
JZ SCNEXT
CPI SPECL ;MAY BE PROCESSOR TECH'S COMMENT
JNZ SCN1
;SPECIAL CHARACTER, CHECK FOR *
LDA ACCUM
CPI '*'
JNZ CHEND ;END OF LINE IF NOT *
; * FOUND, NO PRECEDING LABEL ALLOWED
CALL SETLA
JNZ STERR ;ERROR IF LABEL
JMP CHEN1 ;SCAN THE COMMENT OTHERWISE
;
SCN1: ;NOT NUMBER OR SPECIAL CHARACTER, CHECK FOR IDENTIFIER
CPI IDEN
JNZ STERR ;ERROR IF NOT
;
;IDENTIFIER FOUND, MAY BE LABEL, OPCODE, OR MACRO
CALL BGET ;BINARY SEARCH FIXED DATA
JZ CHKPT ;CHECK FOR PSEUDO OR REAL OPERATOR
;
;BINARY SEARCH WAS UNSUCCESSFUL, CHECK FOR MACRO
CALL LOOKUP
CALL FOUND
JNZ LFOUN ;NZ FLAG SET IF FOUND
;
;NOT FOUND, ENTER IT
CALL ENTER ;THIS MUST BE PASS
LDA PASS
ORA A
CNZ ERRP ;PHASE ERROR IF NOT
JMP SETSY ;SET SYLAB
;
;ITEM WAS FOUND, CHECK FOR MACRO
LFOUN:
CALL GETTY
CPI MACT
JNZ SETSY
;
;MACRO DEFINITION FOUND, EXPAND MACRO
CALL ERRN ;NOT CURRENTLY IMPLEMENTED
JMP CHEN1 ;SCANS TO END OF CURRENT LINE
;
SETSY: ;LABEL FOUND - IS IT THE ONLY ONE?
LHLD SYLAB
MOV A, L
ORA H
CNZ ERRL ;LABEL ERROR IF NOT
LHLD SYADR ;ADDRESS OF SYMBOL
SHLD SYLAB ;MARK AS LABEL FOUND
;
;LABEL FOUND, SCAN OPTIONAL ':'
CALL SCAN
LDA TOKEN
CPI SPECL
JNZ SCN0 ;SKIP NEXT SCAN IF NOT SPECIAL
LDA ACCUM
CPI ':'
JNZ SCN0
JMP SCNEXT ;TO IGNORE ':'
;
;BINARY SEARCH FOUND SYMBOL, CHECK FOR PSEUDO OR REAL OP
CHKPT:
CPI PT ;PSEUDO OPCODE?
JNZ CHKOT
;
;PSEUDO OPCODE FOUND, BRANCH TO CASES
MOV E, B ;B HAS PARTICULAR OPERATOR NUMBER
MVI D, 0 ;DOUBLE PRECISION VALUE TO D,E
DCX D ;BIASED BY +1
LXI H, PTTAB ;BASE OF JUMP TABLE
DAD D
DAD D
MOV E, M
INX H
MOV H, M
MOV L, E
PCHL ;JUMP INTO TABLE
;
PTTAB: ;PSEUDO OPCODE JUMP TABLE
DW SDB ;DB
DW SDS ;DS
DW SDW ;DW
DW SEND ;END
DW SENDIF ;ENDIF
DW SENDM ;ENDM
DW SEQU ;EQU
DW SIF ;IF
DW SMACRO ;MACRO
DW SORG ;ORG
DW SSET ;SET
DW STITLE ;TITLE
;
SDB:
CALL FILAB ;SET LABEL FOR THIS LINE TO ASPC
SDB0:
CALL SCAN ;PAST DB TO NEXT ITEM
LDA TOKEN ;LOOK FOR LONG STRING
CPI STRNG
JNZ SDBC ;SKIP IF NOT STRING
LDA ACCLEN
DCR A ;LENGTH 1 STRING?
JZ SDBC
;LENGTH 0,2,... STRING
MOV B, A
INR B
INR B ;BECOMES 1,3,... FOR 0,2,... LENGTHS
LXI H, ACCUM ;ADDRESS CHARACTERS IN STRING
SDB1:
DCR B ;COUNT DOWN TO ZERO
JZ SDB2 ;SCAN DELIMITER AT END OF STRING
PUSH B ;SAVE COUNT
MOV B, M ;GET CHARACTER
INX H
PUSH H ;SAVE ACCUM POINTER
CALL FILHB ;SEND TO HEX FILE
POP H
POP B
JMP SDB1
SDB2:
CALL SCAN ;TO THE DELIMITER
JMP SDB3
;
;NOT A LONG STRING
SDBC:
CALL OPAND ;COMPUTE OPERAND
LHLD EVALUE ;VALUE TO H,L
MOV A, H
ORA A ;HIGH ORDER MUST BE ZERO
CNZ ERBD ;DATA ERROR
MOV B, L ;GET LOW BYTE
CALL FILHB
SDB3: ;END OF ITEM - UPDATE ASPC
CALL SETAS ;SET ASPC TO FPC
CALL DELIM
CPI ','
JZ SDB0 ;FOR ANOTHER ITEM
JMP CHEND ;CHECK END OF LINE SYNTAX
;
SDS:
CALL FILAB ;HANDLE LABEL IF IT OCCURRED
CALL PADD ;PRINT ADDRESS
CALL EXP16 ;SCAN AND GET 16BIT OPERAND
XCHG ;TO D,E
LHLD ASPC ;CURRENT PSEUDO PC
DAD D ;+EXPRESSION
SHLD ASPC
SHLD FPC ;NEXT TO FILL
JMP CHEND
;
SDW:
CALL FILAB ;HANDLE OPTIONAL LABEL
SDW0:
CALL EXP16 ;GET 16BIT OPERAND
PUSH H ;SAVE A COPY
MOV B, L ;LOW BYTE FIRST
CALL FILHB ;SEND LOW BYTE
POP H ;RECLAIM A COPY
MOV B, H ;HIGH BYTE NEXT
CALL FILHB ;SEND HIGH BYTE
CALL SETAS ;SET ASPC=FPC
CALL DELIM ;CHECK DELIMITER SYNTAX
CPI ','
JZ SDW0 ;GET MORE DATA
JMP CHEND
;
SEND:
CALL FILAB
CALL PADD ;WRITE LAST LOC
LDA PBUFF
CPI ' '
JNZ CHEND
CALL EXP16 ;GET EXPRESSION IF IT'S THERE
LDA PBUFF
CPI ' '
JNZ SEND0
SHLD EPC ;EXPRESSION FOUND, STORE IT FOR LATER
SEND0:
MVI A, ' '
STA PBUFF ;CLEAR ERROR, IF IT OCCURRED
CALL SCAN ;CLEAR CR
LDA TOKEN
CPI SPECL
JNZ STERR
LDA ACCUM
CPI LF
JNZ STERR
JMP ENDAS ;END OF ASSEMBLER
;
SENDIF:
JMP POEND
;
SENDM:
CALL ERRN
JMP POEND
;
SEQU:
CALL SETLA
JZ STERR ;MUST BE A LABEL
LHLD ASPC ;HOLD TEMP ASPC
PUSH H ;IN STACK
CALL EXP16 ;GET 16BIT OPERAND
SHLD ASPC ;VALUE OF EXPRESSION
CALL FI LAB
CALL PADDR ;COMPUTED VALUE
LXI H, PBUFF+6 ;SPACE AFTER VALUE
MVI M, '='
POP H ;REAL ASPC
SHLD ASPC ;CHANGE BACK
JMP CHEND
;
SIF:
CALL FILAB ;IN CASE OF LABEL
CALL EXP16 ;GET IF EXPRESSION
LDA PBUFF
CPI ' '
JNZ CHEND ;SKIP IF ERROR
MOV A, L ;GET LSB
RAR
JC CHEND ;TRUE IF CARRY BIT SET
;
;SKIP TO EOF OR ENDIF
SIF0:
CALL SCAN
LDA TOKEN
CPI SPECL
JNZ SIF1
LDA ACCUM
CPI EOF
MVI A, 'B' ;BALANCE ERROR
CZ PERR
JZ ENDAS
JMP SIF0 ;FOR ANOTHER
SIF1: ;NOT A SPECIAL CHARACTER
CPI IDEN
JNZ SIF0 ;NOT AN IDENTIFIER
CALL BGET ;LOOK FOR ENDIF
JNZ SIF0 ;NOT FOUND
CPI PT ;PSEUDO OP?
JNZ SIF0
MOV A, B ;GET OPERATOR NUMBER
CPI PENDIF ;ENDIF?
JNZ SIF0 ;GET ANOTHER TOKEN
JMP POEND ;OK, CHECK END OF LINE
;
SMACRO:
CALL ERRN
JMP CHEND
;
SORG:
CALL EXP16
LDA PBUFF
CPI ' '
JNZ CHEND ;SKIP ORG IF ERROR
SHLD ASPC ;CHANGE PC
SHLD FPC ;CHANGE NEXT TO HIT
CALL FILAB ;IN CASE OF LABEU
CALL PADD
JMP CHEND
;
SSET:
CALL SETLA
JZ STERR ;MUST BE LABELLED1)
;
CALL GETTY
CPI SETT
CNZ ERRL ;LABEL ERROR
MVI A, SETT
CALL SETTY ;REPLACE TYPE WITH 'SET'
CALL EXP16 ;GET THE EXPRESSION
PUSH H ;SAVE IT
CALL SFTLA ;RE-ADDRESS LABEL
POP H ;RECLAIM IT
CALL SETVAL
LXI H, 0
SHLD SYLAB ;PREVENT LABEL PROCESSING
JMP CHEND
;
;
STITLE:
CALL ERRN ;NOT IMPLEMENTED
;
POEND: ;PSEUDO OPERATOR END - SCAN TO NEXT TOKEN
CALL SCAN
JMP CHEND
;
;NOT A PSEUDO OPCODE, CHECK FOR REAL OPCODE
CHKOT:
SUI 01 ;BASE OF OPCODES
CPI 015 ;PAST LAST OPCODE?
JNC STERR ;STATEMENT ERROR IF SO
;
;FOUND OPCODE, COMPUTE INDEX INTO TABLE AND JUMP TO CASE
MOV E, A
MVI D, 0
LXI H, OPTAB
DAD D
DAD D
MOV E, M
INX H
MOV H, M
MOV L, E
PCHL ;JUMP TO CASE
;
OPTAB: ;OPCODE CATEGORIES
DW SSIMP ;SIMPLE
DW SLXI ;LXI
DW SDAD ;DAD
DW SPUSH ;PUSH/POP
DW SJMP ;JMP/CALL
DW SMOV ;MOV
DW SMVI ;MVI
DW SACCI ;ACCUM IMMEDIATE
DW SLDAX ;LDAX/STAX
DW SLHLD ;LHLD/SHLD/LDA/STA
DW SACCR ;ACCUM-REGISTER
DW SINC ;INC/DCR
DW SINX ;INX/DCX
DW SRST ;RESTART
DW SIN ;IN/OUT
;
SSIMP: ;SIMPLE OPERATION CODES
CALL FILHB ;SEND HEX VALUE TO MACHINE CODE FILE
CALL SCAN ;TO NEXT TOKEN
JMP INCPC
;
SLXI: ;LXI H,16B
CALL SHDREG ;SCAN DOUBLE PRECISION REGISTER
CALL CHCOM ;CHECK FOR COMMA FOLLOWING REGISTER
CALL SETADR ;SCAN AND EMIT DOUBLE PRECISION OPERAND
JMP INCPC
;
SDAD: ;DAD B
CALL SHDREG ;SCAN AND EMIT DOUBLE PRECISION REGISTER
JMP INCPC
;
SPUSH: ;PUSH B POP D
CALL SHREG ;SCAN SINGLE PRECISION REGISTER TO A
CPI 111000B ;MAY BE PSW
JZ SPU0
;NOT PSW, MUST BE B,D, OR H
ANI 0010000B ;LOW BIT MUST BE 0
CNZ ERRR ;REGISTER ERROR IF NOT
SPU0:
MOV A, C ;RECALL REGISTER AND MASK IN CASE OF ERROR
ANI 110000B
ORA B ;MASK IN OPCODE FOR PUSH OR POP
JMP FILINC ;FILL HEX VALUE AND INCREMENT PC
;
SJMP: ;JMP 16B/ CALL 16B
CALL FILHB ;EMIT JMP OR CALL OPCODE
CALL SETADR ;EMIT 16BIT OPERAND
JMP INCPC
;
SMOV: ;MOV A,B
CALL SHREG
ORA B ;MASK IN OPCODE
MOV B, A ;SAVE IN B TEMPORARILY
CALL CHCOM ;MUST BE COMMA SEPARATOR
CALL EXP3 ;VALUE MUST BE 0-7
ORA B ;MASK IN OPCODE CPM VERSION
JMP FILINC
;
SMVI: ;MVI A,8B
CALL SHREG
ORA B ;MASK IN OPCODE
CALL FILHEX ;EMIT OPCODE
CALL CHCOM ;SCAN COMMA
CALL SETBYTE ;EMIT 8BIT VALUE
JMP INCPC
;
SACCI: ;ADI 8B
CALL FILHB ;EMIT IMMEDIATE OPCODE
CALL SETBYTE ;EMIT 8BIT OPERAND
JMP INCPC
;
SLDAX: ;LDAX B/STAX D
CALL SHREG
ANI 101000B ;MUST BE B OR D
CNZ ERRR ;REGISTER ERROR IF NOT
MOV A, C ;RECOVER REGISTER NUMBER
ANI 010000B ;CHANGE TO B OR D IF ERROR
ORA B ;MASK IN OPCODE
JMP FILING ;EMIT OPCODE
;
SLHLD: ;LHLD 16B/ SHLD 16B/ LDA 16B/ STA 16B
CALL FILHB ;EMIT OPCODE
CALL SETADR ;EMIT OPERAND
JMP INCPC
;
SACCR: ;ADD B
CALL EXP3 ;RIGHT ADJUSTED 3BIT VALUE FOR REGISTER
ORA B ;MASK IN OPCODE
JMP FILINC
;
SINC: ;INR B/DCR D
CALL SHREG ;GET REGISTER
ORA B
JMP FILINC
;
SINX: ;INX H/DCX B
CALL SHREG
ANI 001000B ;MUST BE B D M OR SP
CNZ ERRR ;REGISTER ERROR IF NOT
MOV A, C ;RECOVER REGISTER
ANI 110000B ;IN CASE 0F ERROR
ORA B ;MASK IN OPCODE
JMP FILINC
;
SRST: ;RESTART 4
CALL SHREG ;VALUE IS 0-7
ORA B ;OPCODE MASKED
JMP FILINC
;
SIN: ;IN 8B/0UT 8B
CALL FILHB ;EMIT OPCODE
CALL SETBYTE ;EMIT 8BIT OPERAND
JMP INCPC
;
FILINC: ;FILL HEX VALUE FROM A, BEFORE INCREMENTING PC
CALL FILHEX
;
INCPC: ;CHANGE ASSEMBLER'S PSEUDO PROGRAM COUNTER
CALL FILAB ;SET ANY LABELS WHICH OCCUR ON THE LINE
CALL SETAS ;ASPC=FPC
JMP CHEND ;END OP LINE SCAN
;
;
;UTILITY SUBROUTINES FOR OPERATION CODES
;
DELIM: ;CHECK DELIMITER SYNTAX FOR D^TA STATEMENTS
LDA TOKEN
CPI SPECL
CNZ ERRD
LDA ACCUM
CPI ','
RZ
CPI ';'
RZ
CPI CR
CNZ ERRD
RET
;
EXP16: ;GET 16BIT VALUE TO H,L
PUSH B
CALL SCAN ;START SCANNING OPERAND FIELD
CALL OPAND
LHLD EVALUE ;VALUE TO H,L
POP B
RET
;
EXP8: ;GET 8BIT VALUE TO REG A
CALL EXP16
MOV A, H
ORA A
CNZ ERRV ;VALUE ERROR IF HIGH BYTE NOT ZERO
MOV A, L
RET
;
EXP3: ;GET 3BIT VALUE TO REG A
CALL EXP8
CPI 8
CNC ERRV ;VALUE ERROR IF >=8
ANI 111B ;REDUCE IF ERROR OCCURS
RET
;
SHREG: ;GET 3BIT VALUE AND SHIFT LEFT BY
CALL EXP3
RAL
RAL
RAL
ANI 111000B
MOV C, A ;COPY TO C
RET
;
SHDREG: ;GET DOUBLE REGISTER TO A
CALL SHREG
ANI 001000B ;CHECK FOR A,C,E, OR L
CNZ ERRR ;REGISTER ERROR
MOV A, C ;RECOVER REGISTER
ANI 110000B ;FIX IT IF ERROR OCCURRED
ORA B ;MASK OPCODE
JMP FILHEX ;EMIT IT
;
SETBYTE: ;EMIT 16BIT OPERAND
CALL EXP8
JMP FILHEX
;
SETADR: ;EMIT 16BIT OPERAND
CALL EXP16
JMP FILADR
;
CHCOM: ;CHECK FOR COMMA FOLLOWING EXPRESSION
PUSH PSW
PUSH B
LDA TOKEN
CPI SPECL
JNZ COMER
;SPECIAL CHARACTER, CHECK FOR COMMA
LDA ACCUM
CPI ','
JZ COMRET ;RETURN IF COMMA FOUND
COMER: ;COMMA ERROR
MVI A, 'C'
CALL PERR
COMRET:
POP B
POP PSW
RET
;
CHEND: ;END OF LINE CHECK
CALL FILAB ;IN CASE OF A LABEL
LDA TOKEN
CPI SPECL
JNZ STERR ;MUST BE A SPECIAL CHARACTER
LDA ACCUM
CPI CR ;CARRIAGE RETURN
JNZ CHEN0
;CARRIAGE RETURN FOUND, SCAN PICKS UP LF AND PUSHES LINE
CALL SCAN
JMP SCNEXT
;
CHEN0: ;NOT CR, CHECK FOR COMMENT
CPI ':'
JNZ CHEN2
CALL FILAB ;IN CASE LABELLED EMPTY LINE
;CLEAR COMMENT TO END OF LINE
CHEN1:
CALL SCAN
LDA TOKEN
CPI SPECL
JNZ CHEN1
LDA ACCUM
CPI LF
JZ SCNEXT
CPI EOF
JZ ENDAS ;END 0F ASSEMBLY IF EOF
CPI '!'
JZ SCNEXT ;LOGICAL END OF LINE
JMP CHEN1 ;NONE OF THE ABOVE
;
;NOT CR OP LF. MAY BE LOGICAL END OF LINE
CHEN2:
CPI '!'
JZ SCNEXT
CPI EOF
JZ ENDAS
;
;STATEMENT ERROR IN OPERAND FIELD
STERR:
MVI A, 'S'
CALL PERR
JMP CHEN1 ;TO DUMP LINE
;
DIFF: ;COMPUTE DE-HL TO HL
MOV A, E
SUB L
MOV L, A
MOV A, D
SBB H
MOV H, A
RET
;
ENDAS: ;END OF ASSEMBLY FOR THIS PASS
LXI H, PASS
MOV A, M
INR M ;PASS NUMBER INCREMENTED
ORA A
JZ RESTART
CALL SCAN ;TO CLEAR LAST LINE FEED
CALL PADD ;WRITE LAST ADDRESS
LXI H, PBUFF+5
MVI M, CR ;SET TO CR FOR END OF MESSAGE
LXI H, PBUFF+1
CALL PCON ;PRINT LAST ADDRESS
;
;COMPUTE REMAINING SPACE
LHLD SYTOP
XCHG
LHLD SYBAS
CALL DIFF ;DIFFERENCE TO H,L
PUSH H ;SYTOP-SYBAS TO STACK
LHLD SYMAX
XCHG
LHLD SYBAS
CALL DIFF ;SYMAX-SYBAS TO H,L
MOV E, H
MVI D, 0 ;DIVIDED BY 256
POP H ;SYTOP-SYBAS TO H,L
CALL DIVF ;RESULT TO DE
XCHG
CALL PADDR ;PRINT H,L TO PBUFF
LXI H, PBUFF+5 ;MESSAGE
LXI D, EMSG ;END MESSAGE
ENDA0:
LDAX D
ORA A ;ZERO?
JZ ENDA1
MOV M, A
INX H
INX D
JMP ENDA0
;
EMSG:
DB 'H USE FACTOR', CR, 0
;
ENDA1:
LXI H, PBUFF+2 ;BEGINNING OF RATIO
CALL PCON
LHLD EPC
SHLD FPC ;END PROGRAM COUNTER
JMP EOR
;
; UTILITY SUBROUTINES
COMDH: ;COMPARE D,E WITH H,L FOR EQUALITY (NZ FLAG IF NOT EQUAL)
MOV A, D
CMP H
RNZ
MOV A, E
CMP L
RET
;
SETAS: ;ASPC=FPC
LHLD PPC
SHLD ASPC
RET
;
SETLA: ;SYADR-SYLAB, FOLLOWED BY CHECK FOR ZERO
LHLD SYLAB
SHLD SYADR
CALL FOUND
RET
:
FILAB: ;FILL LABEL VALUE WITH CURRENT ASPC, IF LABEL FOUND
CALL SETLA
RZ ;RETURN IF NO LABEL DETECTED
;
;LABEL FOUND, MUST BE DEFINED ON PASS-1
LXI H, 0
SHLD SYLAB ;TO MARK NEXT STATEMENT WITH NO LABEL
LDA PASS
ORA A
JNZ FIL1
;
;PASS 0
CALL GETTY
PUSH PSW ;SAVE A COPY OF TYPE
ANI 111B ;CHECK FOR UNDEFINED
CNZ ERRL ;LABEL ERROR
POP PSW ;RESTORE TYPE
ORI PLABT ;SET TO LABEL TYPE
CALL SETTY ;SET TYPE FIELD
LHLD ASPC ;GET CURRENT PC
CALL SETVAL ;PLACE INTO VALUE FIELD
RET
;
FIL1: ;CHECK FOR DEFINED VALUE
CALL GETTY
ANI 111B
CZ ERRP ;PHASE ERROR
;GET VALUE AND COMPARE WITH ASPC
CALL GETVAL ;TO H,L
XCHG
LHLD ASPC
CALL COMDH
CNZ ERRP ;PHASE ERROR IF NOT THE SAME
RET
;
FILHEX: ;WRITE HEX BYTE IN REGISTER A TO MACHINE CODE FILE IF PASS
MOV B, A
FILHB:
LDA PASS
ORA A
MOV A, B
JZ FILHI
;
;PASS - 1, WRITE HEX AND PRINT DATA
PUSH B ;SAVE A COPY
CALL DHEX ;INTO MACHINE CODE FILE
;MAY BE COMPLETELY EMPTY LINE, SO CHECK ADDRESS
LDA PBUFF+1
CPI ' '
LHLD ASPC
CZ PADDR ;PRINT ADDRESS FIELD
;
LDA NBP
CPI NBMAX ;TRUNCATE CODE IF TOO MUCH ON THIS LINE
POP B ;RECALL HEX DIGIT
JNC FILHI
;ROOM FOR DIGIT ON THIS LINE
MOV A, B
CALL WHEXB ;WRITE HEX BYTE TO PRINT LINE
FILHI:
LHLD FPC
INX H
SHLD FPC ;READY FOR NEXT BYTE
RET
;
FILADR: ;EMIT DOUBLE PRECISION VALUE FROM H,L
PUSH H ;SAVE A COPY
MOV B, L
CALL FILHB ;LOW BYTE EMITTED
POP H ;RECOVER A COPY OF H,L
MOV B, H
JMP FILHB ;EMIT HIGH BYTE AND RETURN
;
;UTILITY FUNCTIONS FOR PRINTING HEX ADDRESSES AND DATA
CHEX: ;CONVERT TO HEX
ADI '0'
CPI '0'+10
RC
ADI 'A'-'0'-10
RET
;
WHEXN: ;WRITE HEX NIBBLE
CALL CHEX ;CONVERT TO ASCII FROM HEX
LXI H, NBP
MOV E, M ;NEXT POSITION TO PRINT
MVI D, 0 ;DOUBLE PRECISION
INR M ;NBP=NBP+1
LXI H, PBUFF
DAD D
MOV M, A ;STORE IN PRINT BUFFER
RET
;
WHEXB: ;WRITE HEX BYTE TO PRINT BUFFER
PUSH PSW
RAR
RAR
RAR
RAR
ANI 0FH ;HIGH ORDER NIBBLE NORMALIZE IN A
CALL WHEXN ;WRITE IT
POP PSW
ANI 0FH
JMP WHEXN ;WRITE AND RETURN
;
PADD:
LHLD ASPC
PADDR: ;PRINT ADDRESS FIELD OF PRINT LINE FROM H,L
XCHG
LXI H, NBP ;INITIALIZE NEXT TO FILL
PUSH D ;SAVE A COPY OF NBP 'S' ADDRESS
MOV A, D ;PRINT HIGH BYTE
PUSH D ;SAVE A COPY
CALL WHEXB
POP D
MOV A, E
CALL WHEXB
POP H ;ADDRESSING NBP
INR M ;SKIP A SPACE AFTER ADDRESS FIELD
RET
;
ERRR: ;EMIT REGISTER ERROR
PUSH PSW
PUSH B
MVI A, 'R'
CALL PERR
POP B
POP PSW
RET
;
ERRV: ;EMIT VALUE ERROR
PUSH PSW
PUSH H
MVI A, 'V'
CALL PERR
POP H
POP PSW
RET
;
ERRD:
PUSH PSW
MVI A, 'D' ;DATA ERROR
JMP ERR
;
ERRP:
PUSH PSW
MVI A, 'P'
JMP ERR
;
ERRL:
PUSH PSW
MVI A, 'L' ;LABEL ERROR
JMP ERR
;
ERRN:
PUSH PSW
MVI A, 'N' ;NOT IMPLEMENTED
;
ERR:
CALL PERR
POP PSW
RET
;
SYLAB:
DS 2 ;ADDRESS OF LINE LABEL
EPC:
DS 2 ;END PC VALUE
NBP:
DS 1 ;NEXT BYTE POSITION TO WRITE FOR MACHINE CODE
END
Last edited by zzz19760225 on 2018-1-1 at 08:11 ]
作者: zzz19760225
时间: 2016-6-26 19:55
DEBUG.EXE指令说明
DEBUG
a 编写汇编语言程序的指令,sta为启始地址
c sta end sta2 比较两个储存单元,sta为第一储存单元的启始地址,而end为第一储存单元结束地址,sta2为第二储存单元的启始地址
c sta lnn sta2 比较两储存单元,sta为第一储存单元启始地址,而nn为欲比较的长度大小,sta2为第二储存单元启始地址
d 显示某指定范围储存单元至屏幕(sta:启始、end:结束)
d 显示某指范围块储存单元至屏幕(sta:启始、nn:长度)
e 修改储存单元中某一个byte的资料,sta为地址
e 修改储存单元中某一个byte的资料,data为新资料
g 执行程序,直至结束地址(end)或程序结束时
g=sta 执行从启始(sta)直至结束(end)或程序结束时
r 显示所有存储器内容或修改某指定存储器(reg)值
t 单步执行,num指定一次执行几步(预设1)
t=sta 单步执行,从sta起始,num指定执行几步(预设1)
n filename 为目前正在编辑或除错的文件命名
w 储存文件,写入cx个bytes的资料至n指定的文件名
w sta dri sec num 将sta资料写入dri磁盘的第sec磁区共写num个磁区
l 载入文件,读出n指定文件,档名的资料至sta地址中
l sta dri sec num 读出dri磁盘的第sec磁区的资料至sta共读num个磁区
q 离开debug,返回DOS
u 反汇编,从sta至end
u 反汇编,从sta,共反汇编nn个bytes
m sta end sta2 将第一储存单元的数据搬至第二储存单元中
m sta lnn sta2 将第一储存单元的数据搬至第二储存单元中
f sta end data 将一段资料(data)存入某指定的储存单元区
f sta lnn data 将nn个bytes的资料存入某指定的储存单元区
s sta end data 搜寻data资料在指定地址内,data不限长度
s sta lnn data 搜寻data资料在指定地址内,data不限长度
h data data2 计算两个资料的和与差并显示在屏幕上
i inport 由输入埠输入并显示一个byte
o outport 由输出埠输出一个byte值
Last edited by zzz19760225 on 2017-11-29 at 00:45 ]
作者: zzz19760225
时间: 2016-6-26 19:56
1
作者: zzz19760225
时间: 2016-6-26 19:57
1
作者: zzz19760225
时间: 2016-6-26 19:58
1
作者: zzz19760225
时间: 2016-6-26 19:59
1
作者: zzz19760225
时间: 2016-6-26 19:59
1
作者: zzz19760225
时间: 2016-6-26 20:00
1
作者: zzz19760225
时间: 2016-6-26 20:01
1
作者: zzz19760225
时间: 2016-6-26 20:06
1
作者: zzz19760225
时间: 2016-6-26 20:07
1
作者: zzz19760225
时间: 2016-6-26 20:08
1
作者: zzz19760225
时间: 2016-6-26 20:09
1
作者: zzz19760225
时间: 2016-6-26 20:10
1
作者: zzz19760225
时间: 2016-6-26 20:12
1
作者: zzz19760225
时间: 2016-6-26 20:13
1