# asm_for_all **Repository Path**: sliyb/asm_for_all ## Basic Information - **Project Name**: asm_for_all - **Description**: 原创汇编代码集锦 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: http://tieba.baidu.com/p/3818941022 - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 9 - **Created**: 2015-09-07 - **Last Updated**: 2020-12-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 本共享库采用GPLV3许可证,请在所有提交代码开头包括许可证,如下: ``` ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . ``` - 目标:共享一些常用代码块,以及示例代码。代码请遵循[规范](http://tieba.baidu.com/p/3818941022)。为方便索引生成,请在开头注释中说明开发环境和最佳编译运行环境、版本;程序整体用途,输入输出,备注等。范例:[TIME_DELAY.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/TIME_DELAY.asm)。 - 库结构:分成example(示例),与template(代码块)。分别再按照指令集(x86,arm...)与系统(console,win32,linux...)分两层,如下: - example -- x86 --- console --- win32 --- linux(暂无) -- arm(暂无) - template -- x86 --- console --- ... 管理员责任:对不同用户共享的代码进行走查(code review),根据代码规范对开发者(包括其他管理员)进行修改建议。 根据代码开头的注释,生成代码索引如下。工具代码请见[项目管理工具/IndexGenerator](http://git.oschina.net/zhishi/asm_for_all/tree/master/项目管理工具/IndexGenerator). [ 4chess.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/ 4chess.asm) 程序名称:4chess.asm 功能:四子棋(棋盘游戏) 环境:16BIT DOS实模式(windows/dos或dosbox)最好全屏 编译器:MASM 5.1-6X (这个是com格式,masm5.x须用EXE2BIN 4CHESS.EXE 4CHESS.COM,Masm6.x须加入:ml /AT参数 用法:看说明 返回值:没有 破坏寄存器:不适用 简易版四子棋简介: 四子棋是一款普遍流行的简易型桌面游戏,据说,虎克船长曾因专注于此游戏而长期隐身在住所,当船员们发现船长的这一专长之后,他们称这个游戏为“船长的情妇”。 四子棋是个双人游戏,两人轮流下棋,棋盘由行和列组成的网格,每个选手每次下一个子直到两人中有一人的棋子连成一条水平线、垂直线或者是对角线。 本实验需要在LC-3中实现简易版四子棋的游戏,两位选手通过键盘和输出窗口轮流交互操作,棋盘由6X 6的网格组成。 游戏规则如下: 两位选手依次轮流落子; 选手没有悔棋; 有子的地方不能继续落子; 直到有一方的四个棋子能够连成一条水平线、垂直线或者是对角线; 如果棋盘已满,无人获胜,则平局。 解题: 游戏是6x6棋盘,连四可以有横,直和斜。 一行中,六中连四,即是三种方式,6列X3即18 同理,直行也是18 斜也是18 换言之,全部胜利条利是18*3=54种。 这样少的条件,直接制作一个表,只要是表内的就是胜利 6X6共36BIT 四字是DQ (64BBIT),即54个DQ的阵列就是胜利条件表 样子大约是 win_table label byte dq 111100000000000000000000000000000000b 这是横列的1个资料 注意:这只是一个范例程式,具备最起码的功能,没有太花巧的技术,也没有人机对战, 若你需要其他功能或加入或删减任何代码,请随便,但不能要求作者为你订制特定的功能或 根据功课要求而改变这个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) 因为没多少空闲,程序只加了一些简单解释。 Connect Four Chess [2014cal.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/2014cal.asm) 程序名称:2014cal.asm 功能:1980-2099年历 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 原题目:http://tieba.baidu.com/p/3817224129 实验设计:年历(2014) 原题目只要求制作2014年历,但这不具通用性,现在这个是1980-2099的年历, 每一次显示半年,按左右键查询其他年份,按ESC閃人。 其实吧里已有TajuraTong姑娘曾写了一个,功能十分完整。 http://tieba.baidu.com/p/3680768090 只要稍稍修改就可以显示半年历了,我已征得TajuraTong姑娘的同意修改她的 程式,在这里发布她的心得和释出她的代码/和本人小部份修改, 这个程式包括想法和技术细节,都是她原创,本人纯粹是一只copycat。 ----------TajuraTong的理论---------------- 程式在纯dos下或者window 的 dosbox也可(最好用全萤幕) 。 R,L 和 <- -> 均可左右查看月份,年份范围由(1980-2099),这是int 21h的限制。按ESC可离开。 int 21h里ah=2ah是读取日期,ah=2bh是设定日期,代码中没有建立每年/每月的资料结构,查看月份时才即时读取。 想法: 读日期时,windows用日期函数,dos的可以用int21h,2ah 或者系统中断int 1Ah 看看int21h好了,int 21h里ah=2ah是读取日期,ah=2bh是设定日期 先看看2A是做什么的: INT 21 - DOS 1+ - GET SYSTEM DATE AH = 2Ah Return: CX = year (1980-2099) DH = month DL = day ---DOS 1.10+--- AL = day of week (00h=Sunday) 其中AL很重要,等于当天日期的星期数!我们只要把日期先 [设定]是某月的第1日, 然后再读取该日的日期,那么就知道该月的第1日是星期一、二还是什么! 接下来再看看ah=2Bh INT 21 - DOS 1+ - SET SYSTEM DATE AH = 2Bh CX = year (1980-2099) DH = month (1-12) DL = day (1-31) Return: AL = status 00h successful FFh invalid date, system date unchanged 注意这个AL = 状态,若是0表示成功,ff表示失败! 我们知道,一年的月份中,最少是28日,最多是31日,只要由28日(dl=28)开始设定该月日期, 成功则日期就dl +1,即29,再回去试,若再成功再dh+1回去试,试到32日,回存失败(al=ff) 那最后的dl减1,就是该月的天数,这样就不用理会什么月大月小,二月有28或29日的麻烦问题了。 到此,我们已经解决了两个关键问题,该月第一天的星期数,该月是28-31那一项? 好了,设想完毕,开始设计表格! 先排日期,我们把它排到惯见的方式: db ' 1 2 3 4 5 6 7 ' db ' 8 9 10 11 12 13 14 ' db '15 16 17 18 19 20 21 ' db '22 23 24 25 26 27 28 ' db '29 30 31 ' 每一个日期占3byte,[空白][word],word=2byte即日期,由1-31 月份: db 'January ','February ','March ','April ' db 'May ','June ','July ','August ' db 'September ','October ','Novermber ','December ' 占14bytes,每个月份等长,不足的补以空白,这样,用指标x14,就是月份的字串位置了 指标可以用左右键去加或减。 再建立一个日历的字串缓冲,形式如下: 年份 / 月份    <-可变 S M T W T F S  <-不变   1 2 3 4 5 6 7 8 9 10 11 12 13 14  < -1到6列可变 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 方法: 0.先把原来日期存起来,int21, ah=2ah,得到年/月/日,存起来当作[年指标]和[月指标]的初始值 1.利用设定和读取得出,算出该月的第一天星期数和该月的天数,把该年由hex转成文字存到缓冲字串的起点 2.月份,利用月份指标x14得出该月字串存到缓冲区 3.送星期字串, S M T W T F S 到缓冲区 4.利用该月第1天的星期数x3,跳过日期第一列的空白,星期数多少就跳多少,得出的位置就是第1日的目的位置 5.利用该月天数x3,得出要搬动多少byte到上面[4]得出的位置28天就搬28x3,31天就搬31x3,来源是 day_str 6.搬完后,日历字串缓冲完成,开始由印缓冲字串 7.利用int21 ah=2,或者int 10 ah=13h列印8列文字,每印完一列,游标移下一列。 8.利用int 16h, ah=0读取使用者输入,RL <- -> 9,加减年份变数 或 加减月份变数,判定正确后回到代码 s10地址,重新清空缓冲字串 根据年份变数和月份变数调数搬移的资料和位置,回到方法:1 10.若输入ESC则离开,回存已经预先读好的原来日期。 ----------TajuraTong的理论(完)---------------- 注意:这只是一个范例程式。 若你需要其他功能或加入或删减任何代码,请随便,但不能要求作者为你订制特定的功能或 根据功课要求而改变这个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) 因为没多少空闲,程序只加了一些简单解释,若不明白看一下TajuraTong的理论就是。 (2015/7/1补充) 关于显示日历的子程序(print_day),原本是用int10h/ax=1300H的方式 但不同的win/dos,dos模拟器对这个函数支缓不足,导致显示不出 现在提供另外两个方法 1.沿用int10h/ax=1300H 2.利用int10h/Ax=09 (基本上和方法1等价,只是代码稍复杂) 3.利用最原始的dos int 29h(黑底白字) 哪种方法适合,自己取用吧 -------------------------------------------------------- [2014easy.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/2014easy.asm) 程序名称:2014easy.asm 功能:2014年历简化版 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 原题163楼 http://tieba.baidu.com/p/3740277941?pn=5 这个简化版以之前的2014cal.asm做蓝本 利用2014/1/1是星期三,和 month_days db 31,28,31,30,31,30,31,31,30,31,30,31 这两个资料计算其余的月份,不用int21函数, 背景和其他复杂的技术, 只加了计算月份的count_month_day而已 [2014fool.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/2014fool.asm) 程序名称:2014fool.asm 功能:2014年历陽春版 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 原题163楼/166楼 http://tieba.baidu.com/p/3740277941?pn=5 要求:如果还没学BIOS中断,不用int 10h这些,仅用DOS的int 21h中断该怎么写啊? 这个[陽春版]以之前的2014easy.asm做蓝本 应要求,不用int10h,只用3个int21h/ah=7读键,ah=09印字,ah=4ch离开 [4calc.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/4calc.asm) 程序名称:4calc.asm 功能:四则运算(10/16进制四则) 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 可计算10/16进制四则,平方和平方根。 10进制,个数限制10个,范围(0-4294967295),超过限制会印出overflow。 16进制,个数限制8个, 范围(0-FFFFFFFF)。 第1运算元输入后,可按+-* /,或P或S (平方/平方根)。 然后输入第2运算元,再按[=]或[回车],即时显示答案,显示最多18位。 小数则显示最多20位。 若在第1运算元时,按[空白]即时转换10进制和16进制。 转制后仍可进行四则运算。 若是16进制除,结果可能有小数,所以均以10进制显示 注意1:这只是一个范例程式,具备最起码的功能,没有太花巧的技术。 若你需要其他功能或加入或删减任何代码,请随便,但不能要求作者为你订制特定的功能或 根据功课要求而改变这个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) 注意2:伸手党拿去取用没问题,但[不能]在代码任何位置或标题或程式上加上个人资料, 例如作者谁谁谁,或者Written by XXX等等,这代码是本人的烂创作,不是谁或谁写的东西 本人都不加名字了! 没多少空闲,程序只加了一些简单解释,若要探入理解代码运作, 请自行debug,不要问我,或要求增加注解。 代码及程式 http://pan.baidu.com/s/1pJxGSor 4calc.txt(代码) 和4calc.exe是最后版本,包含所有功能 4basic.txt(代码)和4calc.exe是较早版本,只包含10进制四则 没有平方和平根,也没有即时转制,较适合伸手党, 4basic.txt没有解释,可自行在4calc.txt或下面抄解释,不要烦我! ---------------------------------------------------------------------- 常数设定 [ASCII2BCD.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/ASCII2BCD.asm) 下行定义你的CPU MODEL [DOS文本写显存.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/DOS文本写显存.asm) 下行定义你的CPU MODEL [Dir_a_file.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/Dir_a_file.asm) 这是一个印出档案资料最最基本的程式,它先建立一个DTA 再呼叫int21h / ah=4eh找出档案的资料,然后依次印出 档名,档案大小,最後修改日期和最後修改时间 若给出档名有万用字元如* 和?,再用int21h / ah=4fh ,第二个找到的 档案可再在DTA抓出资料,如此类推,这相当于部份dir的功能 [Directory_list.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/Directory_list.asm) 上一个程式dir_a_file.asm是印出指定档案的资料,这个增加一些功能, 首先读入参数,例如键入的参数是 A*.*,程式就以A*.*作为搜寻的目标, 若没有输入参数,则以*.*(万用字元)作为搜寻的目标。 同样利用int21h / Ah=4Eh做第一次搜寻,印出,再利用int21h / Ah=4Fh 做后续搜寻,直到传回cf=1为止,表示当前文件夹再也找不到档案了, 最后印出全部显示档案和文件夹的总数。 程式执行时,可按ESC离开,按空白键暂停。 这程式实现了DOS的DIR部份功能,没有实现的是多层文件夹和排序等等, 留待有空再说了。 [DispRegM.inc](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/DispRegM.inc) DispRegM.inc 这是testreg.asm子程序,请看testreg.asm说明 副程序名称:dispregM.inc 功能:配合regsub.inc的宏 环境:16BIT DOS实模式 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:没有 [HEX2ASCII.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/HEX2ASCII.asm) [HEX2BCD.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/HEX2BCD.asm) 下行定义你的CPU MODEL [HEXVIEW.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/HEXVIEW.asm) [Little_clock.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/Little_clock.asm) 程序名称:clock.asm 功能:常驻计时器/闹钟 环境:16BIT DOS实模式 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 这是吧上某人的功课吧 这题目有普遍性,涉及的问题较多,所以独立发一帖,希望多些人看到. 参照 “定时响铃”的例子及其它MASM程序的例子,实现 INT 1C MYINT1C 实现的功能在屏幕的右上角显示秒表或时钟,按ESC, 退出程序。 说明: 1.实现基本的秒表功能,即参照8.5范例给出的响铃程序改写, 实现简单的计时和暂停、中止等功能; 2.时钟复杂一些,按照书后BIOS/DOS中断附表实现从系 统取时间,并能够对其进行设置和相应的计时功能。 解题 DOS的常驻,时钟比较简单,基本上拦截1CH,抓取系统时间, 找个地方显示一下就完事了,至于计时,方法也有许多,1CH 本身就是每1/18.2秒运行一次,所以同时也有计时功能. 常驻的方法用DOS的21H,AH=31H或者INT27也可以. 这个小小CLOCK程式的计时和读时间不用任何中断int21h,ah=2ch 或int 1Ah,而是直接读取40:6C - 40:6D的系统累加时间,这相容度好像 还大,测试在windows/dos 和dosbox都能正常运行 编译:因为程式是com,masm 5.x 须要exe2bin 转成com> exe2bin clock.exe clock.com masm 6.x的话加 ml /AT 的设定可直接转成com 用法: clock ;在右上角显示时间 clock u ; 移除常驻 clock s mm:ss mm是分钟,ss是秒 键入clock s 3:10   右上角显示倒数计时3:10 ..3:09...3:08 直到00:00时显示3秒红色 -alarm-文字 然后回到正常系统时间 若键入 clock s 10,程式会视为倒数10分钟,若只要倒数秒 可键入 clock s 0:10 ;则数10秒 若clock已经常驻,也可以键入clock s mm:ss 去设定新的倒数 代码有简单的英文注解(要交功课的同学请自行添加/翻译注解) [NameTelREC.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/NameTelREC.asm) 程序名称:NameTelREC.asm 功能:人名/电话简单记录表 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 这是贴吧上一个问题,什么也没有,只有一幅加重肩颈炎病情的图。 http://tieba.baidu.com/p/3829872119 题目要求建立一个只有9个人名/电话资料的资料纪录,包括输入和查询功能,列出全部/刪除记录是我手痒加的。 题目有普通性,代码示范了查询和表列的技术,并不复杂。 加了簡單的解釋,若不明白,debug一下就是。 注意:这只是一个范例程式,具备最起码的功能,没有太花巧的技术。 若你需要其他功能或加入或删减任何代码,请随便,但不能要求作者为你订制特定的功能或 根据功课要求而改变这个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) [RDCMOS.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/RDCMOS.asm) 下行定义你的CPU MODEL head 磁头 track 磁道 sector 扇区 Sector of per Track 每磁道扇区数 [SQRT_calculate.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/SQRT_calculate.asm) 程序名稱:計算平方根 功能:輸入一個帶小數的數,計算平方根並輸出 環境:16BIT DOS實模式 編譯器:MASM 5.1-6X 用法:輸入一數(可帶小數),按ENTER [TIME_DELAY.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/TIME_DELAY.asm) 副程序名稱:delay_proc 功能:時間延遲 環境:16BIT DOS實模式 編譯器:MASM 5.1-6X 用法:把延遲秒數放入AX,呼叫delay_proc 返回值:沒有 破壞寄存器:沒有 備註:若AX=0,即時返回 [TestReg.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/TestReg.asm) 程序名称:Testreg.asm 功能:利用子程序印出所有寄存器(范例程式) 环境:16BIT DOS实模式 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:没有 --------- register_display (Sub program)------------ 原发问人希望改为子程序。 于是有了这个,可以说是之前X86_Register_display.asm的进阶版。 改写完了,我发觉这个小玩意也有一点用途。 它可以实时显示所有寄存器,子程序运行之后,因不改变寄存器值, 这就相当于一个软中断,放在程式的某些需要监视变数、观看loop值, 或者查看呼叫中断后传回的值.....等等场合,都能适用。 为了简便使用,我分别写了两个inc档,Regsub.inc 和DispRegM.inc Regsub.inc是子程序,DispRegM.inc是一个宏 另外写了一个测试用Testreg.asm,就是现在这个。 使用方法: (1)纳入inc档,在档顶加入一句:include dispregm.inc  因为宏中会使用push 立即数的代码,所以档顶至少要加入.286或以上(如.386) (2)纳入inc档,在档尾加入一句:include regsub.inc (3)可在程序中任何位置加入宏,如   @DisplayReg 10,01  ; 立即值,在第10行,印出01(蓝色)的全部寄存器值  or @DisplayReg AX,BX ;寄存器赋值,用AX和BX指定的行和颜色  or @DisplayReg variable1,variable2 ;变数赋值,用变数指定的行和颜色 要注意的是,若要插入@DisplayReg 的程式是驻留式的 即是使用int21h/ah-31h 或int 27h那种常驻程式,则 include regsub.inc [必须]放在驻留部份的最底 ----------- 驻留代码 .驻留的底部...include regsub.inc ---------- 初始化代码 end ---------- 这是一般驻留程式的结构,被载入后会做一些初始化动作, 然后[只]把驻留代码留在内存,初始化代码则[丢弃]! 所以插入的include regsub.inc [必须][必须] 放在驻留部份的最底,否则..... 还有regsub.inc代码里会自行设定.286的伪代码 若初始化代码有用到.386,请自行再加上 就算最顶有.386,也会被regsub.inc的.286取代 若不是驻留程式,则include regsub.inc最好放底 即 .include regsub.inc CODES ENDS END START --Code Start---------------------------------------------------------------- [X86_Register_display.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/X86_Register_display.asm) --------- register_display ------------ Q. 98楼 http://tieba.baidu.com/p/3740277941?pn=3 问题: 现在一个现实问题,大部分初学者,不知道各寄存器的值! 希望写一个打印各寄存器值的程序!不要中断,不要32位汇编! 就像C语言里面的printf函数! 回答: 列印寄存器的值和列印一般资料没什么分别 和列印16bit/32bit的hex值一样......... 其实进入debug ,按R,就是16bit寄存器的值 这个代码正是仿debug [R]的作法,印出各寄存器和Flag的值 但这个不是真正的debug,没有单步,所以CS:IP和flag等,知道了也没什么意义. 倒是可以看看程式被载入时各寄存器的初始值 [Y-ABCDE.ASM](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/Y-ABCDE.ASM) 程序名称:Y-ABCDE.ASM 功能:根据公式,计算Y值 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 应sjydhqhome的遨请,为这烂题目写了一个汇编,正想贴出却发现原贴被删了,好样的! 没有原题目,大概就是读取五个数ABCDE,根据公式: (Y=AxB+C/D-E),把正负结果分别存入BUF1和BUF2... 草草写的这一个,少于300行.. 为了加点趣味和亲和性,所以加了运算元的显示,若不要这些,大概150行就可以了 程式只读入两个数字,接受负数,输入到D值时,若发现为0,不会接受并清除 输入时,程式会显示和指出运算过程,光是这些烂功能就花掉百多行代码.. 结果直接印在后面,这样直观一些.. 按ESC或ENTER离开 时间有限,加了小量解释,没空侦错,若有bug请报告.. -------------------------------------- http://pan.baidu.com/s/1kT7rtiB [bigclock.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/bigclock.asm) 程序名称:clock.asm 功能:常驻计时器/闹钟/大时钟 环境:16BIT DOS实模式 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 这是吧上某人的功课吧 这题目有普遍性,涉及的问题较多,所以独立发一帖,希望多些人看到. 参照 “定时响铃”的例子及其它MASM程序的例子,实现 INT 1C MYINT1C 实现的功能在屏幕的右上角显示秒表或时钟,按ESC, 退出程序。 说明: 1.实现基本的秒表功能,即参照8.5范例给出的响铃程序改写, 实现简单的计时和暂停、中止等功能; 2.时钟复杂一些,按照书后BIOS/DOS中断附表实现从系 统取时间,并能够对其进行设置和相应的计时功能。 解题 DOS的常驻,时钟比较简单,基本上拦截1CH,抓取系统时间, 找个地方显示一下就完事了,至于计时,方法也有许多,1CH 本身就是每1/18.2秒运行一次,所以同时也有计时功能. 常驻的方法用DOS的21H,AH=31H或者INT27也可以. 这个小小CLOCK程式的计时和读时间不用任何中断int21h,ah=2ch 或int 1Ah,而是直接读取40:6C - 40:6D的系统累加时间,这相容度好象 还大,测试在windows/dos 和dosbox都能正常运行 编译:因为程式是com,masm 5.x 须要exe2bin 转成com> exe2bin clock.exe clock.com masm 6.x的话加 ml /AT 的设定可直接转成com 用法: clock ;在右上角显示时间 clock u ; 移除常驻 clock c ;大时钟 clock s mm:ss mm是分钟,ss是秒 键入clock s 3:10   右上角显示倒数计时3:10 ..3:09...3:08 直到00:00时显示3秒红色 -alarm-文字 然后回到正常系统时间 若键入 clock s 10,程式会视为倒数10分钟,若只要倒数秒 可键入 clock s 0:10 ;则数10秒 若clock已经常驻,也可以键入clock s mm:ss 去设定新的倒数 补充: 增加大时钟功能:- 吧友问题,希望能够在DOS窗口中以像素点形式对绘制一个数字时钟或表盘时钟; 有基本的控制操作,例如:修改时间、控制时钟显示位置等(自行发挥)。 (较易,但 “分”低)也可绘制最基本的阿拉伯数字时钟, 但必须配合键盘或其他对时钟的一些功能控制! 解: 像素点形式就免了,没这个时间,但其他功能倒可以实现 代码取用楼上的小时钟,保留所有功能,只增加了大时钟 使用方法: clock c 注意:这只是一个范例程式,具备最起码的功能,没有太花巧的技术 若你需要其他功能或加入或删减任何代码,请随便,但不能要求作者为你订制特定的功能或 根据功课要求而改变这个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) 代码有简单的中/英文注解,要交功课的同学请自行添加/翻译注解,不要问我! 交功课的最好不要全抄,应吸收理解后做适当的修改,因为这是本人已公开的代码, 任何人都可以取用,因抄袭而挂科责任自付! [draw_o.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/draw_o.asm) This file draw a circle in the middle of screen the circle can be big than screen,move core position (x,y),change color compile use Miniasm Date & Time: 11:39,30th,july,2014 [find_text.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/find_text.asm) 字符串匹配模块 用户输入的一个句子保存成文件,然后输入一个关键字进行查询。 如果句中不包含关键字则显示"NOMATCH!"(红色字显示), 如果句中包含关键字则显示“MATCH”(白色字显示)并重复显示这段文字, 把匹配的字符用红色显示出来。 其实十分钟的烂程式,为了windows7/8的垃圾dos搞了好一阵子, Xp/dos/win7/8都可正常了,只是使用了不常用的屏幕卷动…. 程序名称:find_ext.asm 功能:找字符 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 -------------------------------------------------------- [hexview.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/hexview.asm) 程序名称:HEXVIEW.ASM 功能:文件的十六进制观看器 HEX VIEWER 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1 (这个是com格式,masm5.x须用EXE2BIN HEXVIEW.EXE HEXVIEW.COM,Masm6.x须加入:ml /AT参数 用法:看说明 返回值:没有 破坏寄存器:不适用 使用方法: HEXVIEW 程式会读入档案,并以十六进制显示,按上下pgup,pgdown,home,end观看,ESC离开 为减少复杂度,最大读入档案大小512k,大于则只读入前512k部份 注意1:这只是一个范例程式,具备最起码的功能,没有太花巧的技术. 若你需要其他功能或加入或删减任何代码,请随便,但不能要求作者为你订制特定的功能或 根据功课要求而改变这个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) 注意2:伸手党拿去取用没问题,但[不能]在代码任何位置或标题或程式上加上个人资料 例如作者谁谁谁,或者Written by XXX等等,这代码是本人的烂创作,不是谁或谁写的东西 本人都不加名字了! 程序只加了一些简单解释,若深入理解程式运作,请自行用debug,不要问我。 代码及程式; http://pan.baidu.com/s/1i3zUvvn [house.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/house.asm) 程序名称:house.asm 功能:益智游戏 环境:16BIT DOS实模式(windows/dos或dosbox)最好全屏 编译器:MASM 5.1-6X (这个是com格式,masm5.x须用EXE2BIN 4CHESS.EXE 4CHESS.COM,Masm6.x须加入:ml /AT参数 用法:看说明 返回值:没有 破坏寄存器:不适用 Q.http://tieba.baidu.com/p/3873497011 一、益智游戏 猜猜房子里有几个人:随机出现M个人从左边进入房子,随机N 个人从右边离开房子 一段时间后,输入房子中的人数。系统判断是否正确。 要求:人物和房子用图形方式实现 解: 当然仍是文字模式,不会真的这么闲去做图形显示, 随便做些小人,时钟和火炬,意思一下算了... 小人随机进入,随机离开,等一段时间询问屋里有多少人数? 答对了Win,答错了lost 注意:这只是一个范例程式,具备最起码的功能,没有太花巧的技术 若你需要其他功能或加入或删减任何代码,请随便,但不能要求作者为你订制特定的功能或 根据功课要求而改变这个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) 因为没多少空闲,程序只加了一些简单解释。 代码及程式 http://pan.baidu.com/s/1hqldS7i [int21k.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/int21k.asm) 程序名称:int21k.asm 功能:驻留或载入程式,拦载int21输入函数01h,07h,0Ah,3Fh,把所有输入写入记录档 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1-6X (这个是com格式,masm5.x须用EXE2BIN int21k.EXE int21k.COM,Masm6.x须加入:ml /AT参数 用法:看说明 返回值:没有 破坏寄存器:不适用 原题目: Q. http://tieba.baidu.com/p/3865431344 通过改变中断让每次进行int21输入中断时 210楼 http://tieba.baidu.com/p/3740277941?pn=7 求问一个题:通过改变int21输入中断舍得每次进行这个中断的时候就会 记录下输入的内容. 解: 若理解没错,是要求做一个驻留程式,然后监视int21的输入函数, 若发现有输入,则把它们记录下来 要搞清楚int21的输入有几多种,常用大约有4种 01:字元输入有显示,返回al 07:字元输入没有显示,返回al 0A:字串输入,ds:dx指向字串缓冲 3F: 读取标准输入stdin , ds:dx指向缓冲,bx=1(标准输入句柄),cx=读入字数 程式开始做一些初始化的工作,建立一个叫int21k.01的档, 若成功则以后输入会记录在这个档上,若失败则再建立int21k.02,若再失败则03... 程式常驻后会监视01,07,0A,3F四个函数,若是则 先记录这个编号,若01,07则记录返回的al,若0A则把输入字串整条抄下来 若3F则把读入(即输入)字元全部记录,写进int21k.0?中 使用方法: INT21   ;常驻内存 int21 filename ;载入并运行参数档 移除方法: INT21 /U 载入并运行的方式不须移除,因为不驻留 若要看结果: TYPE int21k.0? <?视情况而定,通常是1> 记绿的方式是: 0A: abcddieiddei8e 01: 6 其中最前两个是函数编号,[:]后是输入值 0A:或3F:后通常是一串字符,01或07后是一个字节 执行int21完后,随便在dos键入一些垃圾即可 注意,许多软件并不使用int21h输入函数,而直接用int16h,甚至int 09 但题目没拦int16h的要求,也就不理了,也不会特意去写,因为 int16h几乎统驭所有输入,记录超级庞大不算,也会影响其他程式运作! ---关于int 60h的说明--- DOS一般预留INT 60H-INT69H(好像是79H,不太记得了)作为使用者中断,换言之, 程式师可以设计自己的中断,比如要利用INT60H, 就先写一段中断代码,然后更改中断向量表, 令表中的INT60h偏移指向自己的中断,再在程式中 呼叫INT60H即可 读写中断向量可以用INT21H /35H和25H 驻留程式,不管静态也好,动态也好,必须要拦截中断,否则无法运作自己的代码, 比如要写一个小时钟(静态),就拦截INT1CH或者INT8,比如要写一个驻留计算机(动态), 就要拦截INT9h,时时刻刻监视有否自己的热键,随时准备弹出, 无论怎样,程式都不能独占中断,拦截INT9h,若不是自己的热键,就要运行原来的中断, 让当前程式正常运作,一般的作法是 Pushf ;保存标志 Call dword ptr old_int9ip ;呼叫原int9中断 返回后,再运行自己的代码 这种方法在绝大部份中断可行,但int21h是例外,换言之,不能 Pushf ;保存标志 Call dword ptr old_int21ip ;呼叫原int21中断 上面的写法会有不可预期的错误,但可以这样写 Pushf ;保存标志 jmp dword ptr old_int21ip ;直接跳到原int21中断 问题来了,跳去int21h,怎么知道返回值是多少,尤其我们要读取输入嘛! 于是有人想出int60h替代原int21h的方法,我也忘了是不是我想出来的, 总之是,先把int21h的中断地址,写入int60h处(中断向量表) 然后在代码中,凡有int21h的地方改int60h 然而仍有问题,int60h是否已被占用? Int60h被占用,int61H没吧或者int62H,int63H….于是有了(set_init )子程序的做法,这处就不多话了 注意:这只是一个范例程式,具备最起码的功能,没有太花巧的技术, 若你需要其他功能或加入或删减任何代码,请随便,但不能要求作者为你订制特定的功能或 根据功课要求而改变这个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) 因为没多少空闲,程序只加了一些简单解释。 代码及程式 http://pan.baidu.com/s/1dDdcoCx (新) http://pan.baidu.com/s/1c0ttptu -------------------------------------------------------------- [regsub.inc](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/regsub.inc) 副程序名称:regsub.inc 功能:印出所有寄存器 环境:16BIT DOS实模式 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:没有 regsub.inc 这是testreg.asm子程序,请看testreg.asm说明 [studREC.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/studREC.asm) 程序名称:StudREC.asm 功能:學生積分记录表 环境:16BIT DOS实模式(windows/dos或dosbox) 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 这是贴吧上一个问题 http://tieba.baidu.com/p/3861969926 成绩管理模块,完成学生的姓名和成绩输入,计算出平均成绩, 并显示出来。其中,把学生的成绩显示出来,及格的用蓝色, 不及格用红色显示。输入界面参考如下:“时候需要输入” “请输入学生姓名”“请输入学生成绩” 这是根据NameTelREC.asm的代码,因应要求做了小小修改,加了平均分和上色 注意:这只是一个范例程式,具备最起码的功能,没有太花巧的技术。 若你需要其他功能或加入或删减任何代码,请随便,但不能要求作者为你订制特定的功能或 根据功课要求而改变这个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) 没多少空闲,程序只加了一些简单解释,若要探入理解代码运作, 请自行debug,不要问我,或要求增加注解。 -------------------------------------------------------------------------------- [三数排序.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/三数排序.asm) 设有3个单字节无符号数存放在BUF开始的缓冲区中,编写一个能将它们从大到小从新排列的程序。 [字数据数组排序.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/字数据数组排序.asm) 设某一数组的长度为N个元素,均为字数据,试编制一个程序使该数组中的数据按照从小到大的次序排列。(要从大到小排序,只需把JBE改为JAE即可) [正负数判断.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/正负数判断.asm) 判断一个数X的正,负数,还是零。(假设是正数,输出+,是负数,输出-,是零,输出This is a zore !) [范围0-16求最小数.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/范围0-16求最小数.asm) 求十个数中的最小数,并以十进制输出。(若要求最大的,只要把JC 改为JNC 即可)(仅局限于0---16间的数比较,因为ADD AL,30H只是针对一位的十六进制转换十进制的算法) [駐留時鐘(註解).asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/console/駐留時鐘(註解).asm) 程序名称:clock.asm 功能:常驻计时器/闹钟 环境:16BIT DOS实模式 编译器:MASM 5.1-6X 用法:看说明 返回值:没有 破坏寄存器:不适用 这是吧上某人的功课吧 这题目有普遍性,涉及的问题较多,所以独立发一帖,希望多些人看到. 参照 “定时响铃”的例子及其它MASM程序的例子,实现 INT 1C MYINT1C 实现的功能在屏幕的右上角显示秒表或时钟,按ESC, 退出程序。 说明: 1.实现基本的秒表功能,即参照8.5范例给出的响铃程序改写, 实现简单的计时和暂停、中止等功能; 2.时钟复杂一些,按照书后BIOS/DOS中断附表实现从系 统取时间,并能够对其进行设置和相应的计时功能。 解题 DOS的常驻,时钟比较简单,基本上拦截1CH,抓取系统时间, 找个地方显示一下就完事了,至于计时,方法也有许多,1CH 本身就是每1/18.2秒运行一次,所以同时也有计时功能. 常驻的方法用DOS的21H,AH=31H或者INT27也可以. 这个小小CLOCK程式的计时和读时间不用任何中断int21h,ah=2ch 或int 1Ah,而是直接读取40:6C - 40:6D的系统累加时间,这相容度好像 还大,测试在windows/dos 和dosbox都能正常运行 编译:因为程式是com,masm 5.x 须要exe2bin 转成com> exe2bin clock.exe clock.com masm 6.x的话加 ml /AT 的设定可直接转成com 用法: clock ;在右上角显示时间 clock u ; 移除常驻 clock s mm:ss mm是分钟,ss是秒 键入clock s 3:10   右上角显示倒数计时3:10 ..3:09...3:08 直到00:00时显示3秒红色 -alarm-文字 然后回到正常系统时间 若键入 clock s 10,程式会视为倒数10分钟,若只要倒数秒 可键入 clock s 0:10 ;则数10秒 若clock已经常驻,也可以键入clock s mm:ss 去设定新的倒数 這個和之前的little_clock是一樣的,只是加了中文解釋,為免影響編譯,所以另開一個 若有編譯錯誤,請下載little_clock. [HEX2ASCII.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/win32/HEX2ASCII.asm) MASMPlus 代码模板 - 控制台程序 [fbird.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/example/x86/win32/fbird.asm) 程序名称:fbird.asm(未完成版) 功能:flappyBird游戏 环境:Windows视窗游戏 编译器:MASM32 用法:看说明 返回值:没有 破坏寄存器:不适用 用Win32汇编写FlappyBird FlappyBird未完成版,尚欠碰撞测试,拿金币,计分,生命, GameOver,音乐,音效,关卡设计等等,完成度20% 材料:- 1.masm32版,网上自找,最好用 \MASM32 作为文件夹 2.FlappyBird背景图,文字图,柱子及小鸟图,网上抓 3.Photoshop任何版本,把背景图裁剪为游戏窗口的1/4大小 若游戏窗口是800x400,背景图做成200x400,(见压缩包里的4back.bmp) 注意左右拼合起来时,不要看见接驳痕迹. 把抓回来的小鸟褪去背景色,改为全黑背景(透明色), 利用旋转另制作七个小鸟的方向图,分别为 右,右下,下,左下,左,左上,上,右上 合拼八图,增加版面,把flappybird横牌和上下柱子合成一图 (见压缩包里的birdAA.bmp) 记录每一个图像在合拼图的位置和宽长(参看代码中的birdA_offset) 原理:- 1.这种横向2D游戏通常同时有背景卷动和主角移动,我们设定了一个55ms的计时器 invoke SetTimer,NULL,NULL,55,addr _ProcTimer 即是说, 每55ms(1/18秒)系统会呼叫 _ProcTimer 一次,大部份工作都在这程序完成. 2.读取背景图,4个背景图合成一张游戏窗口背景图, invoke LoadBitmap,hInstance,100 其中100是背景图编号,由rsrc.rc指定 为什么要合拼而不完整一张呢?原因是bmp挺大,一个大bmp随时1m以上, 若改为jpg需额外代码处理,不如bmp方便 用BitBlt函数连续做12(4x3)次合拼,做了一张3个窗口大小的背景暂存(memDC2) 我们叫它1号窗口,2号窗口和3号窗口 另外建立一个窗口大小的显示暂存(memDC3) 设定一个卷动变数var1,每1/18秒轮到_ProcTimer运行时,var1+5 1,2号窗口是一张1600宽的暂存图(memDC2的1和2),每次显示时, 由x=var1,y=0的位置开始搬(memDC2)800x400的资料出来放显示暂存(memDC3) 再把小鸟动作,柱子,金币或各种物件依位置放在显示暂存(memDC3) 最后刷新屏幕时由显示暂存(memDC3)一次置入当前窗口中, 由于var1不断增加,x不断变动,这样就会做成背景卷动和主角移动的效果 当var1累加到达800,视界也到达第2号窗口,这时var1置0, 2号窗口资料搬到1号窗口,3号窗的原始背景移到2号窗口,重新绘上柱子或其他物件 这样,柱子和新物件就源源不断由右方卷出来 3.原代码中有详细注解,在这里也不再多说了,若有不明白地方欢迎提出, 更欢迎指出不足之处,毕竟俺也少写这类程式,错漏难免.... 4注意:这只是一个范例程式,若你需要其他功能或加入或删减任何代码, 请随便,但不能要求作者为你订制特定的功能或,根据功课要求而改变这 个子程序改变那个子程序,若是代码错误或优化代码的意见, 则欢迎提出:) 压缩包:- 链接:http://pan.baidu.com/s/1o6IL6gM 密码:ecx1 压缩包,有源码,资源档,图档和make.bat 运行make.bat即可完成编译 ---------------------- 以下是flappyBird源码 ---------------------------- [TextOutput.asm](http://git.oschina.net/zhishi/asm_for_all/blob/master/template/x86/console/TextOutput.asm)