小赖子的英国生活和资讯

步步高多媒体学生电脑机器码编程教程(转)

阅读 桌面完整版

步步高多媒体学生电脑是1996年上市的以家用电视为显示器的键盘式电脑,包含标准国际键盘~游戏手柄及鼠标和标准3.5寸软驱,可以运行BBGDOS步步高电脑英文操作系统~BBGCdos步步高中文操作系统~步步高WIN98图形操作系统~五笔字型~WPS文字处理系统~BEXCEL电子表格~BASIC语言~DEBUG汇编调试程序~BASM汇编工具及数十种学习软件和数百个任天堂兼容游戏.支持外接针式打印机~与PC机联机运行并调用PC机硬盘.尤其是它内置的3.5寸标准软驱功能,可以永久存储数据并和其他电脑交流数据,可以方便廉价地升级扩充功能,从而使它与当时市场上流行的大量电脑学习机有了本质的区别,所以步步高多媒体学生电脑是一台标准电脑而不只是一台只能打字娱乐的游戏学习机.

利用步步高多媒体学生电脑可以学习电脑操作知识,可以打字写文章打游戏,还可以自己编程,使这个电脑干任何你能想到的任务.

网友在2014年开发出了在PC机window系统上的步步高多媒体学生模拟器,使这个当年名扬海内外的名字重新焕发了活力.在步步高多媒体学生电脑上当年就可以用debug.cmd这个软件实现书写机器码并存盘自行开发软件的功能.现在使用步步高模拟器上你也可以运行任何你在电脑上开发的程序.需要什么工具呢?在电脑上想进行步步高多媒体学生电脑机器码编程需要准备三个工具:

1~步步高模拟器含系统盘镜像文件
2~winhex.exe,一个16进制编辑器工具软件(也可以使用其他类似工具注意WINDOWS自带的记事本和写字板~word/wps等字处理软件都不可以.).
3~winimage.exe,一个可以新建~修改软盘镜像文件的工具.后两个软件各大软件下载网站都有下载,百度即可找到.有了这三个工具后,让我们就开始在电脑上开始步步高多媒体学生电脑机器码编程之旅吧!

一~最短的程序(reset.cmd)
在电脑上用winhex.exe或在步步高多媒体学生电脑上使用debug.cmd新建一个文件,输入06 58两个字节,另存为reset.cmd(或任意一个文件名,必须以.cmd结尾,本文以后凡是提到另存为一个cmd格式的文件时都只要求此新文件的扩展文件名是.cmd,下同).在步步高真机上直接运行这个只有2个字节的程序.你会发现电脑重新启动了.在PC机电脑上使用winimage.exe把这个reset.cmd文件按inject按钮添加到一个步步高多媒体学生电脑的启动盘中,并按save按钮存盘.然后把这个启动盘(如bbk.img)文件拖到步步高多媒体学生电脑模拟器(VirtuaNESex.exe,下载地址:http://pan.baidu.com/share/home?uk=1896123392#category/type=0)中运行.输入reset.cmd后回车,你会发现模拟器重新启动了.和在步步高真机上一模一样.

二~编一个hello程序(hello.cmd)
一般编程课程总是从编一个hello程序开始的.我们这里也不例外.打开winhex,输入:00 80A0 0F A2 80 A9 04 20 0C 58 A9 00 A8 20 0C 58 48 45 4C 4C 4F 2400,另存为hello.cmd文件.在步步高真机上或者步步高模拟器中运行hello.cmd,DOS屏幕上成功输出了hello五个字母.

上面这个程序中,从第17个字节开始是非程序的数据区,即要屏幕输出的字符串内容,前17个字节是程序基本上一个字节也不能变.而数据区可以随意设置你想要显示的内容,而且不限长度,想显示很长的文章也是可以的.(最大可以输出三万个汉字呢!)唯一的要求是,你输入的这个字符串必须以2400(16进制)结尾.

前16个字节是什么意思呢?一个一个讲吧.前2个字节:0080,是一个程序语句.就是要求步步高电脑系统从$8000内存开始装入本程序.第3到6字节是规定了待显示字符串的内存地址从800f开始.第7~8两个字节(A904)是调用DOS的显示字符串功能.和9~10~11三个字节(200c58)是DOS功能入口.第12~13字节(A900)是调用DOS的程序结束返回操作系统的功能.第14字节是设置返回时的方式.第15~16~17(200c58)字节第二次出现了,不用讲了.
这里要指出一点:前两个字节在以后的内存地址计算时需要减2.本程序字符串实际开始地址是第18字节($11),除掉开头0080两个字节的位置,11就变成0F了.从8000开始,加0F个字节.字符串开始显示的位置是$800F($开头的数表示这是16进制).

三~显示一个字符的程序(14个字节)—(a.cmd)
16进制机器码:00 80 A2 42 A9 0220 0C 58 A9 00 20 0C58,一共14个字节,其中第4个字节是要输出的字符($42=#50=”B”).A902也是一项DOS功能调用,功能是输出一个字符.这个功能和上边那A904功能相比更简单,不需要计算操作作内存地址指针(如$800F).直接用A2加16进制ASC码就可以了.机器码A2在汇编语言源程序中表达叫LDX,意思是给6502CPU的X寄存器直接赋值.相当于VB中的:dimx as byte;x=”B”;
那么我再掉头看第二个HELLO程序的第3~4~5~6字节(A0 0F A280),您是不是明白了一点.那里也有一个A0机器码,没错,那就是LDX$0f这句汇编语言语句的机器码.等于:X=$0f=#15=15;明白了吧.
这里加一点硬件知识.6502CPU有三个(不止三个,先这三个)8位寄存器(即一个字节,只能存储一个字节):A~X~Y.相当于VB中的三个全局变量:publicA as byte,X as byte,Y asbyte.每个寄存器可以输入~输出~存储~改变.和VB中的全局变量完全一样.A2是LDX(给X赋值,如X=$80(VB语言),LDX80(汇编语言),A2 80(机器码)),A0是LDY(给Y赋值,y=0F,LDY $0F,A0 0F),A9是LDA([机器码:A902]=[汇编:LDA 02]=[vb:A=02]).

四~什么也不显示的程序
机器代码:00 80 A9 00 A8 20 0c58;程序运行后什么也不显示就退出程序返回到DOS.(Null.cmd)
机器代码:00 80 a8 A9 00 20 0c58;程序运行后显示”Return from running programe”后退出程序返回到DOS.
这有什么用呢?它的作用就是没有死机.正确地执行了A900这个DOS功能(结束程序退出到操作系统).其中你看到了,每个程序中都必须有200c58代码.机器码20等于VB的CALL命令或者GOTO~goSUB命令.而0c58这4个字节呢,是调用DOS功能的总开关($580c).不执行020c58这个语句(相当于VBSCRIPT的RUN命令或者F5命令,重要吧),程序就什么也不做(包括回到DOS操作系统这个您最熟悉的地方),这不就是死机了嘛.而A900(汇编源程序是lda#$00,把00这个字节内容送入6502的A寄存器又叫累加器.00是什么?00=步步高DOS功能调用接口的第一个功能,返回操作系统:DosProgramReturn=0)呢,是告诉电脑我这个程序要结束了.没有这4个字节,电脑也会死机.因为程序不会返回到操作系统.你就无法进行下一步的电脑操作了,只能重新启动而且是通过按电源的方法.至于头4个字节,参照HELLO程序理解吧.你也可以自己修改删除这4个字节看看会有什么反应.好不好?

五~机器码程序设置电脑的中英文模式.(CdosTest.cmd)
步步高DOS第12项调用接口是DosGetSetDispMode,equ=11=$0b,我们来学习一下.

*****************************这一段太长.可以不看.想深入理解的再回头找其中的知识点看比较容易.直接看最后的结果******************************
*****************************但是这个思考过程其实很有学习的价值.只是需要耐心和时间而已.想快就不看,想深研就慢慢看**************************

这是步步高公司赵福海先生提供的汇编语言源程序:

isccdos
{
;****************************************************
;* isccdos
;****************************************************
isccdos:
    jsr getmode
    cmp #$80
    beq isccdosY
    sec
    rts
isccdosY:
    clc
    rts
    import getmode
}

下面我们把它改编为机器码程序:

isccdos 这一行不需要编译(叫伪代码)
{       也不用      
;****************************************************
;* isccdos        以;分号开头的全部不编译,是注释
;****************************************************
isccdos:        声明了一个子程序.子程序名:isccdos.汇编语言的子程序如果只运行一次,就不需要编译了.但是如果它被第二次甚至多次调用的话,就必须记住它的开始地址了.
    jsr getmode  调用getmode子程序.
    cmp #$80     =c980比较A寄存器和80H一样不一样
    beq isccdosY =f0?? ?? 如果一样就跳转到isccdosY子程序.
    sec        =38意思:设置进位标志
    rts        =60子程序结束标志.机器码叫:60,单字节.不需要参数.作用是返回到本子程序调用指令的下一个字节处.
isccdosY:      声明了一个子程序.子程序名:isccdosY 机器码调用子程序是用4c加子程序的开始地址.如4C8000.即转到内存中8000地址处的子程序.
    clc        =18 意思是清除进位标志
    rts        =60 子程序结束了
    import getmode请输入或粘贴名叫getmode的子程序
}   不用

这里又出来一个名叫getmode的子程序. 我们再把这个子程序拿出来看看吧.

getmode         伪代码
{             伪代码
getmode:    ;子程序声明.需要记住它的开始地址.上面那个程序有两次要调用这个地址.
lda #DosGetSetDispMode  =A90b 其中:lda=a9,#DosGetSetDispMode=$0b=#$0b=0bH=#11
ldx #0     =A200,把0这个字节存到X寄存器.
    jmp DosIOEntry =200c58.这个不用说了吧.每个程序每次调用DOS功能都要有这一句才生效.
}             伪代码.子程序结束标志.

下面开始书写机器码:

00 80 规定程序从内存8000开始装入.
4C ?? ?? 转到子程序的地址.还不知道呢.先用????代替吧.
c9 80
38
60
18
60   这是isccdos子程序的最后一句了.
a9 0b这就是getmode子程序的第一句了.是本程序的第12个字节12-2-1=9=09H,地址出来了:$8009,想调用本子程序只要用4c09 80 就可以了.上面的?? ??就写成09 80好了.
a2 00
20 0c 58 输入完成.

再完整地看一下:

00 80 4c 09 80 c9 80 38 60 18 60 a9 0b a200 20 0c 58

用winhex.exe书写以上代码并另存成CCDOS.CMD,用winimage.exe把ccdos.cmd添加(inject)到bbk.img这个软盘镜像文件.启动步步高模拟器,把bbk.img用鼠标拖至模拟器窗口.进入BBGdos后,键盘输入ccdos回车,程序启动了.什么?死机了.哇.忘了加上返回DOS模块了.

再用winhex修改,加上A9 00 A8 20 0c58这几个字节后重新来一遍.成功了:程序什么也没有提示,成功结束并返回到DOS.
你要说这有什么用啊?没什么用.起码没有死机啊,没有报错啊.这就是胜利啊.

那怎么办呢?怎么看到程序的运行结果呢.下面我们对程序再加上一些内容.
这就是要让他显示字符串.这是我们编的第二个程序.现在要用上了.
我要求程序在检测到电脑处于中文模式后输出:CCDOS=yes!电脑处于英文模式是输出:ccdos=no!
把我们的第二个程序粘贴过来再进行一下修改吧.

00 80 A0 0F A2 80 A9 04 20 0C 58 A9 00 A8 20 0C 58 48 45 4C 4C4F 24 00

这个程序其中的前两个字节不需要了(新程序已经有了嘛).其中80 0F 两个字节是地址,也需要在新程序重新写一下.

00 80 4c 09 80 c9 80 38 60 18 60 a9 0b a2 00 20 0c 58 A9 00 A820 0c 58 这个主程序里需要加入一个子程序.

添加过程:00 80 4c 09 80 c9 80 38 60 18
这里加上 显示ccdos=no!字符串的指令
60
这里加上显示CDOS=yes!字符串的指令
a9 0b a2 00 20 0c 58 A9 00 A8 20 0c 58
这里加上两个字符串的数据
6363646F733D796573212400这个字符串在winhex里可以直接输入字符.比如6363就是CC,64就是d,6f就是o,73就是s,不需要背字符的ASC码再输入.但是最后那个00用字符是输不进去的.必须用16进制输入.
6363646F733D6E6F212400 字符串=ccdos=no!

最后结果:00804C0980C980386018A00CA280A904200C5860A030A280A904200C58A90BA200200C58A900A8200C5800000000000000006363646F733D7965732124006363646F733D6E6F212400
写到这里,运行了一下.结果地址不对,胡乱显示.需要修改字符串调用的地址.

我发现,getmode子程序其实只运行了一次,完全不用写在后面然后用跳转地址的方法去调用它.可以直接写在开头.先运行它.就不用跳转了.

***********************************************************************************************************************************************************
***********************************************本程序以上部分是思考过程,可以不看,只看下面的结果可以*******************************************************
00 80 A9 0B A2 00 20 0C 58 C9 00 F0 13 A0 2D A0 2D A2 80 A9 0420 0C 58 A9 00 A8 20 0C 58 FF FF A0 39 A2 80 A9 04 20 0C 58 A9 00A8 20 0C 58 63 63 64 6F 73 3D 79 65 73 21 24 00 63 63 64 6F 73 3D6E 6F 21 24 00
这个新程序运行后,在西文环境下显示:ccdos is no!
最后说一下这个F0字节,后面跟一个字节.这个字节就是偏移量.如01,就是往后面beq指令后跳转一个字节后的内容.中间有几个指节就写成多少.这样似乎不能超过256个.JoyMaker网友说还有符合,那样就是往前入后各最多跳转127个字节.
在中文环境下显示:ccdos is yes!

六~修改一个字节,让中文软件在西文环境下运行.

使用winhex.exe或debug.cmd在中文应用软件内搜索C9 80F0(在第5个程序中我们已经知道这个语句是测试系统是否中文环境的关键),然后将找到之处的80改成00,此西文软件就可以在西文BBGDOS中运行了.不再提示您必须先运行bbgcdos.
(说明:80是中文环境的标志,00是西文环境的标志.c9是把A寄存器中值与它(80或00)比较.F0是个条件选择指令,相当于VB中的if,如果相等就向后跳转多少个字节去执行新命令.如果不相等就不跳转,接着执行下一句.)
七~BBGCDOS出错的地方

1A0F:A9 0B A2 01 A0 80 20 0C 58 就是这个地方一运行就开始出现乱码.
这一句的意思是设置电脑显示模式为中文模式.立即执行.
软件第一句:0064,要求软件装载的内存地址为6400
第二句:4c037d,有条件跳转到7d03地址.7d03=1905H
第三句:a2ff ,x=ff
第4句:9a=txs,意思是S=x=ff
第5句:20527c,又要跑到内存7c52处了,似乎没跑到,电脑在连续执行下一句
第6~7~8~9句:
a9 0b a2 01 a0 80 20 0c 58,这不就是显示中文那一句嘛
第10句:9003=bcc $7d17
11~4cca7d=jmp 7dca
我觉得这两句也可以分开换一种方法反汇编:90034c
ca 7d

强烈推荐

微信公众号: 小赖子的英国生活和资讯 JustYYUK

阅读 桌面完整版
Exit mobile version