![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-07 16:19 |
共 48,041 主题排行 / 350,128 发帖 / 今日 3 篇 / 48,252 会员排行 |
| 网络日志(Blog) » 【Redtek】 个人网志(学习笔记) |
| 可打印版本 29,501 / 130 |
| 第61楼 redtek | 发表于 2006-12-24 06:46 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
关于批处理嵌入超长汇编代码 [原创][批处理单行显示多种颜色字符]
http://www.cn-dos.net/forum/viewthread.php?tid=25797&fpage=0&highlight=&page=2 上面贴子的第27楼: qzwqzw兄提到了:“从可读性上来讲,可以将汇编脚本分行下载批处理前段,这样的形式可以更好的注释”。 感谢qzwqzw兄精彩的指点,原来水平无法实现这个功能,现在可以实现了:) 而且根据qzwqzw兄指点,如果按这种方法做,可以在 .Bat 批处理中嵌入超长汇编代码,如嵌入数百行…… 也就是说可以执行非常复杂的汇编了,且还与批处理合二为一。 而且,这种内嵌方式也解决了纯 MS-DOS 下命令行长度不能过长的一大障碍~:) 如果哪天急了,还可以汇编、批处理、VBS三合一合写一个代码(晕晕……) (刚才测试了一下,有一些障碍~:) [ Last edited by redtek on 2006-12-23 at 06:14 PM ] |
|
| 第62楼 redtek | 发表于 2006-12-24 07:27 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
简单做了一个批处理内嵌汇编代码的实验程序,其最主要的目地是为了完成特殊任务,同时不生成临时文件。
|
|
| 第63楼 redtek | 发表于 2006-12-24 10:13 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 连续的累加指定的内存单元,求和例程。
用 Debug 分析过程。 指令区别: ) Masm mov ax, 将值0传送给ax寄存器 ) Debug 汇编直译 mov ax, 相当于: (ax)= ((ds)*16+0) ) Debug 汇编直译 mov ax,FFFF 将 FFFFH 传送到 ax 寄存器 ) Masm mov ax,0FFFFH 功能同上。但在Masm汇编代码中,数据不能以字母开头,所以前必须加0 解决办法: Masm 中使用段前缀 mov ax,ds: 相当于: (ax)=((ds)*16+0)) [ Last edited by redtek on 2006-12-24 at 09:42 AM ] |
|
| 第64楼 redtek | 发表于 2006-12-24 22:46 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 安全内存空闲空间
|
|
| 第65楼 redtek | 发表于 2006-12-24 23:06 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 段前缀的使用
理解将内存 ffff:0 ~~ ffff:b 单元中的数据拷贝到 0:200~0:20b 单元中的过程。 0:200~~0:20b = 200:0 ~~ 200:b 通过循环拷贝地址中的内容,要初始化偏移地址变量bx,赋值循环次数变量cx,循环12次(0~~b)。 例程
执行后
关于上面代码循环的改进过程…… 每循环都要设置改变两次ds段地址,但效率不高。 使用两个段寄存器分别存放单元 ffff:x 和目标单元 0020:x 的段地址,效率上会提高一些。 改进例程
上面蓝色标注是段前缀的使用,强制指定是哪一个段。 Debug 跟踪调试结果
实验: 1) 编程,向内存 0:200~~0:23F 依次传送数据 0~63(3FH)。 程序中只能使用 9 条指令。 第一次的代码写内存的顺序反了,哈哈…… 重来…… 下面是重写的代码经过Debug调试后发现 0:200 地址处内容本该被写入 00H,结果并没有被写入。 经过Debug跟踪分析,原来我是用cx=3F经循环被Loop递减运算时,当Loop遇3F为0时,则退出了,所以这个00H没机会写入。 看来这种倒着写的方法有待改进:) (下面是错误的内容)
调试正确的代码:
调试成功~:)
如果没有 Debug 调试这个编译的 .exe 文件,根本没有办法直接发现程序中的问题。 越来越感觉到 Debug 就象是用于看到代程序过程并方便调试代码用的(批处理中的) Echo on 这样的命令~:) 而且,没有象 Debug 类似或是一样的工具帮助调试已编译了的代码,将寸步难行~:) 上面代码原理: 从偏移量 0~3F 一共有 64 个字节(因为偏移量0也算一个,刚才给忘了) 所以设置循环 64 次。 将 0:200 (段:偏移量)地址设置为 200:0000 地址( (段*16+偏移量) / 16 :0000 ),方便计算。 所以 bx 寄存器中的偏移量就从 0000 开始计数了~:) 只要计数累加偏移量到 64 时,那个cx计数器中的循环64次也正好结束,所有指定内存全都写入了。 [ Last edited by redtek on 2006-12-24 at 12:33 PM ] |
|
| 第66楼 redtek | 发表于 2006-12-25 01:35 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 关于 Debug 的一个调试技巧
假如不再想跟踪调试上面绿色部分的代码了,想一下子执行完绿色部分的代码, 但只让程序执行到红色标注的代码处停止。 则可以用 g 命令加参数执行: G 0010 含义:从当前 CS:IP 指针处执行代码,执行到标号 0010 处停止。 [ Last edited by redtek on 2006-12-24 at 12:40 PM ] |
|
| 第67楼 redtek | 发表于 2006-12-25 02:27 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 代码复制自身到另一块内存
) 下面的程序的功能是将 "mov ax,4c00h" 之前的指令复制到内存 0:200 处,补全程序。 上机调试,跟踪运行结果。 根据以上代码思考问题: 1) 复制的是什么?从哪里到哪里? 2) 复制的是什么?有多少个?如何知道要复制的字节的数量? 根据上面代码,分析如下: (ds)*16+256B= cs 所以 cs =(ds)+10H 复制的代码不能包括 “mov ax,4c00h” 与 “int 21h” 这两句,如何知道其长度? 反汇编这两句代码信息如下: 其中:B8004C与CD21是上面 mov ……命令的机器码,数一下。机器码是:5个字节。 所以,(代码总长度 - 5B )=要复制的代码长度。 即: CX-5=要复制的但又不含上面两句指令的代码总长度。 所以,循环次数是 cs-5 。cs中具体是多少要Debug调入才知道(或是根据经验数),不过咱们把循环次数瞎添一个就知道了。 下面是补全代码以后,唯一不知道总长度,也不知道要循环多少次。 所以,用汇编代码中的cx循环次数21是瞎写的,先占个长度,这样先能编译过去再说。 然后到了Debug中所看到的红色标注部分就是代码的总长度,我们再用总长度减那两条语句的机器码长度5字节,就是cx循环次数。
长度为 0x001c ,再减那两条不包括的指令的5个字节,为 23 。即直要复制的代码长度为 23 个字节~:) 我是用计算器算的,如果觉得用计算器算太麻烦,还可以向上面一样秀一下DOS命令~:)同样支持16进制与10进制混合运算~:) 补全后的代码 Debug跟踪过程,验证是否将自身代码复制到 0:200 处 下面是反汇编代码,方便参考。
下面是运行代码前的目标内存状态与运行代码后的目标内存状态
下面是执行后的目标内存情况(被拷了过去)
反汇编被拷贝过去的目标内存
看一下主代码(进行复制的主代码)
[ Last edited by redtek on 2006-12-24 at 02:56 PM ] |
|
| 第68楼 redtek | 发表于 2006-12-25 05:28 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 包含多个段的程序
程序取得所需空间的方法: 1) 加载程序的时候为程序分配 2) 程序在执行的过程中向系统申请 dw,字型数据。 在代码中使用数据例程 Debug 跟踪上面编译了的代码 反汇编看到其 dw 所定义的数据被定义到了代码段首(因为dw是第一条指令),其内容如下:
但是,上面的代码会出现问题,因为前16个字节不是代码,而是我们定义的数据。 Debug 分析上面被编译之后的代码
在源程序中指明程序入口所在 Debug 跟踪上面编译了的代码 发现 ip 已指向 10 ,cpu执行时跳过了数据区。 嘿嘿……开始奇怪了,越奇怪思考起来越有味道~:) 病毒?修改程序入口?还能干什么?原由? 比较结果:一个带 end start ,一个是 end ,比较入口不一样的地方 改名比较
FC 执行比较的以后,将它的输出信息copy到这里居然显示“双影儿”字了,哈哈…… fc /b pok.txt pno.txt >test.txt之后,再用Debug重写一个新文件,再次16进制写这几个字,看看是不是重影儿? 打开记事这回是,copy 粘到这里。 记事本内copy这内容看来没事儿,刚才重影是在 cmd 里直接copy 的…… type test.txt 一下,cmd 里copy ^ 好玩…… copy con a.txt 新建一个,直接打字看看 type 出来是什么…… 16进制一样,唯一区别就是 cmd 直接copy,刚一放到 里一粘就是双影,比较剪辑板?晕……………………………… 会不会和 fc 在 cmd 中的输出方式有关?它用了另一种方式显示字符? 而这种方式显示的字符当 copy 到剪辑板时就变成了双字? 看来 echo 是达不到这种效果…… 我看到的 fc 的输出和我copy出来的不同…… 用这种方法进行防批处理运算结果输出中的防拷贝? 测试 fc 比较文件后,输出了一串中文字信息…… 然后直接在cmd里鼠标右键选择copy……一粘结果还是双字…… 奇怪……………… [ Last edited by redtek on 2006-12-24 at 10:49 PM ] |
|
| 第69楼 electronixtar | 发表于 2006-12-25 07:24 |
| 铂金会员 发帖 2,672 积分 7,493 | |
|
牛人,顶
|
|
| 第70楼 ccwan | 发表于 2006-12-25 07:44 |
| 金牌会员 发帖 1,160 积分 2,725 来自 河北廊坊 | |
|
顶,人牛!
|
|
| 第71楼 redtek | 发表于 2006-12-25 10:58 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
多谢两位仁兄鼓励:)
人牛?饶了我吧,嘿嘿……应该一边看着汇编一边咬着牛肉干儿~:)````` |
|
| 第72楼 redtek | 发表于 2006-12-25 22:03 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 数据、代码、栈在不同的段中使用
是圣诞节?时间流逝,冲刺…… 1) 代码、数据、栈放到同一个段中会使程序混乱,难以维护。 2) 如果数据、栈、代码需要的空间超过64KB,就不能放在一个段中。 不同的安排放到不同意义标识的段中,更使代码清晰容易扩展。 将数据、代码、栈放到不同的段中,例程分析: ) 在定义 stack 栈段的代码中,编译器编译给出 "no stack segment" 警告,在 Google.com 查询到的解决办法: 问: 已在程序中设有如下定义:STACK SEGMENT ……为什么LINK 仍然警告:no stack segment ? 答:将段定义修改为:STACK SEGMENT STACK ;后面的STACK项是组合类型,即不再出现警告信息。 多段方式的代码 编译可执行文件后用Debug调试,发现一个错误~:) 发现多了个 00H 00H ,源代码中定义的数据什么时候定义了这个东东? 后来一数,是多了一个数据 00H 00H ,原来是写源代码的时候多加一个逗号,编译器认为这是合法的一个数据 00 00 。
绿色标注相当于源代码中的: 红色标记是源代码中多打了个逗号所占位的。 蓝色标记为栈空间预留,相于源代中的 然后再 Debug 调试,紧接着就是这个有意思的错误。 但如果在 MS-DOS 下调试则没有问题,因为栈并没有越界,它就算是“指针”越界,但数据不会越界(数据长度刚刚好)。 可见(个人目前认为) CMD 太严格了! [ Last edited by redtek on 2006-12-25 at 11:19 AM ] 附件 1.GIF (14.91 KiB) |
|
| 第73楼 redtek | 发表于 2006-12-26 01:12 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 编写调试跟踪多段程序
一个小窍门 刚才希望截取 Debug 操作的过程文字,结果内容过长,无法 copy 文件。 试着Debug输出内容重向到一个文本文件内,好是好,只是生成了临时文件。 想了想发现一个好玩的办法,不生成临时文件,直接将操作过程管道输出到剪辑板内,然后我往论坛一粘就行了~:) 不过,所输出的内容是不会显示到屏幕上的。但是用熟了也用着显示什么,知道自己键入的是什么应该出现些什么就行了。 下面源代码编译后调试跟踪过程 试调上面编译过的源代码
代码装入执行前与执行改变栈地址之后的数据对比
上面是代码装入执行前和改变栈ds的对比,根据上面对比再对比整个代码使用内存的变化。
红色标注为 ss 栈段在代码执行前未重新分配时的状态,ss 基地址批向数据在源代码中的定义: 而紧跟着它后面的数据 00 00 ……则是为栈安排存储区,它在代码中是这样定义的 上面的定义这才是应该为栈分配的空间。 而在这一片 “内存区域” 的后面才是代码入口 ( end start ),cs段地址为:0B4BH 执行前: 执行后(只执行 为ss栈赋值后),则变化如下: 其 ss=B4A0 ,被定义到了原来的栈与代码段之间了(即向下移了16个字节), 由原来装入时的 SS=0B49 向下移了 16字节。 变为: SS=B4A0。 那么 SS=B4A0 它将指向哪里?见上面反汇编分析,其指向了 dw 0,0,0……在源代码中所定义的栈区。 这是为了方便压栈用。 分析: ) CPU执行程序,程序返回前,data 段中的数据为多少? ) CPU执行程序,程序返回前,CS=? SS=? DS=? CS=0B4B SS=0B4A DS=0B49 ) 设程序加载后,code段的段地址为X,则data段的段地址为? stack段的段地址为? stack段的段地址为: stack=(cs)*16+0B-32B data段的段地址为: data=(cs)*16+0B-32B - 100H 编译下面代码,用Debug加载、跟踪、调试…… ) CPU执行程序,程序返回前,data段中的数据为多少? DS = 0B49 DS = 23 01 56 04 ) CPU执行程序,程序返回前, CS、SS、DS都是多少? DS=0B49 SS=0B4A CS=0B4B ) 设程序加载后,code段的段地址为X,则data段的段地址为? stack段的段地址为? stack段的段地址为: ( (X)*16 - 32B) / 16 data 段的段地址为: ( (X)*16 - 32B - 256B) ) / 16 ) 对于如下定义的段: name segment ... name ends 如果段中的数据占N个字节,则程序加载后,该段实际占有空间为? 答:如果 N < FH ,则实际占用 FH 字节。 简单总结: (到这里,发现一个例子反复的跟踪和对比源代码被编译并反汇编后的“样子”是绝对值得的,直到脑子里已经形成视图为止。) (每一个基础如果不打好,就向下走,会学得非常快,但越向后学难度越大、难以逾越的障碍就会越多,能力难以再提高。) (汇编离不开Debug等调试工具,没了这些工具寸步难行。汇编学机器原理,Debug了解真象。) 将下面的程序编译连接,则Debug加载、跟踪…… 分析: {PSP}{代码}{数据}{栈} ) CPU执行程序,程序返回前,data段中的数据为多少? DS=0B4C 0B4C:0000 23 01 56 04 ) CPU执行程序,程序返回前,CS=? SS=? DS=? SS=0B4D CS=0B49 DS=0B4C ) 设程序加载后,code段的段地址为X,则data段的段地址为? stack段的段地址为? 因为 code 段之前没 stack、data 等数据,只有 psp所占用的256B。 所以 data 段地址为: ((CS)*16 - 256B )/ 16 公式写得不太标准。因为文件一被装入,data段自然指向PSP,而stack与data段都在code段后面, 所以code段地址(CS)向回移255B就是PSP。 CX=44H 即:寄存器代码长度为:68 B 实际手工数代码长度为:34 B 则 68B - 34B = 34 B 则视图如下:{有效代码占34B+补满F}{data+补满到F + stack实际占用} (上面只是视图,不是真正计算方法) (因为代码结束后的空余空间在F以前是不再用了,为了整除方便) (所以,再有数据,如栈和数据段的超始地址都是可以将来被16整除的地址,这是最重要的一点) 即: CX代段总长度 - (DATA: dw 0123h,0456h 独占的16倍数的起始行 = 16字节) == DATA段基地址 (CX=68B)-(DATA: 16B)-(最后的stack所真实占用的4B)= 48B(CS段的偏移量) (CS=0B49H)+48B =0B4CH (这是求出的段地址) * 现在我们求出了已知CS地址,所以DATA段的地址为: 0B4CH 那么假如 CS=X ,则DATA段地址为: ((x)*16+48B)/16 * 既然已知DATA段地址了,那么STACK只不过是它向下的一个F篇移量,则STACK= (((x)*16+48B)/16)+16B 下面是一些求得如下公式的推理验证。 -d ss:0 0B49:0000 B8 4D 0B 8E D0 BC 10 00-B8 4C 0B 8E D8 FF 36 00 0B49:0010 00 FF 36 02 00 8F 06 02-00 8F 06 00 00 B8 00 4C 0B49:0020 CD 21 00 00 00 00 00 00-00 00 00 00 00 00 00 00 (上面 CD 21 就是代码结束了) (下面 23 01 56 04 是 dw 0123H,0456H 所定义的数据。) (下面 00 00 00 是 stack 段在源代码中 dw 0,0 定义的栈空间) (它们的特点:都是新起一行:) (它们为什么都要新起一行来存有被定义的新数据?) (个人理解:) (这是带有偏移量的数据,如果计算为无偏移量物理地址为:0B4E:1) (当 MOV AX,0B4E:1 显然无法赋值) (但 MOV AX,B4E1 表面上看上去是物理地址,但它不是相对段地址,所以更是出错) (所以,偏移量只要的后面有0,方便段的物理地址(段)*16+偏移量,它的物理地址低位是0,方便再转为无偏移量 的段地址) 经过分析,反汇编代码 CD 21 (代码结束了)之后是 00 00 …… 因为刚才分析出必须是(段)*16+偏移量以后,其低位必须有0…… 这样形容:就是当段地址*16+偏移量的物地址必须能被16整除才可以。 简单总结: 上面的计算方法并不难,写了这么多笔记是为了推出它们的规律和都是为什么。背一个公式有记记力就行了,那么没有公式的时候怎么办?只能推出解决办法。要想找到解决办法就必须从源代码与反汇编的真实代码之间找到它们的规律, 要找出规律就得用基础知识反复的验算。验算过程中就会发现很多不解的内容,如:为什么要空出一部分空间不用?为什么要新起一行才可以?这些书上没有,怎么办?一遍一遍推,一遍遍算,就会发现很多内容全是基础知识的扩充。 程序的入口地址分析 code segment start: mov ax,stack ……………… ……………… code ends end start 如果没有在源代码中标出程序入口标置会怎么样?什么样的源代码未标置程序入口就不会运行? 分析如下:
编译后的可执行文件,代码入口就是源代码中按顺序放的数据,哈哈……无法运行~:) 从这里就可以看到 Start 与 end Start 的重要性了,它指出了代码结束与代码入口地址。不过start可以随便启名:)
) 将 A 段和 B 段中的数据依次相加,将结果 C 段中。 调试结果
) 用 push 指令将 a 段中 word 数据逆序存储到 b 段中。 跟踪结果如下
[ Last edited by redtek on 2006-12-26 at 11:21 PM ] |
|
| 第74楼 redtek | 发表于 2006-12-27 22:48 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 灵活定位内存地址
and和or指令 ) and 指令 都为1时为1,否则为0 通过该指令可将操作对象的相应位设为0,其它位不变。 设: al,01100011B 将 al 的第6位设为0: and al,10111111B 将 al 的第7位设为0: and al,01111111B 将 al 的第0位设为0: and al,11111110B ) or 指令 都为1时为1,或有一个为1时也为1,否则为0 通过该指令可将操作对象的相应位设为1,其它位不变。 设: mov al,01100011B 将 al 的第6位设为1: or al,01000000B 将 al 的第7位设为1: or al,10000000B 将 al 的第0位设为1: or al,00000001B 对比源代码定义数据与编译后的可执行文件
见到可执行文件其上所定义的数据存放形式
它们是连续存放的~:) 经过分析发现原来源代码中将这些数据定义在一个标号所段内,它们就是连续存放的。如果分开定义,它们就是单独占FH。 下面对比单独定义数据,看它们是如何分布的~:)
Debug 分析它的分布……
上面这两段数据的“间隔”起始偏移地址都相差FH,为了取首地址和定位方便~:) 将字符串中的第一行 “BaSiC” 字母全转成大写 跟踪结果
把第一行字符串全转成大写,第二行字符串全转成小写字母 用 Debug 跟踪结果
如果要是用到批处理里呢? 0X61是小写字母 a 的 ASCII 码的16进制表现形式。a 的10进制 ASCII 码是 97 “&” 符号在批处理的 SET /? 命令帮助中是:“与” 操作。 我们最后结果所得到的 65 ,就是大写字母 A 的 10 进制的 ASCII 码表现形式。 怎么验证 65 就是大写字母 A ? ALT+65 的按键操作就出来了~:) [bx+idta] 一种更灵活的寻址方式,它的偏移地址为(bx)+idata决定~:) 将一个内存单元的内容送入AX,这个内存单元长度为2字节(字单元),存放一个字,偏移地址为bx中数值+200,段地址在ds中。 数学化描述为: (ax)=((ds)*16+(bx)+200) 该指令也可以写成如下格式: mov ax, mov ax,200 mov ax,.200 下面是随便一个例子,对比上面三种命令格式机器码中的表示。 Debug 反汇编看到机器码与反汇编指令如下:
经过对比发现,机器码是一样的,看来这些格式全是MASM干的~:) 用方式进行数组处理 使用数组原理实现将“两行”不同地址的字符串(第一行转大写,第二行转小写) Debug 验证转换结果
SI 和 DI SI 和 DI 是 8086CPU中和bx功能相近的寄存器,SI和DI不能够分成两个8位寄存器来使用。 示例三组指令实现了相同的功能: 1) mov bx,0 mov ax, 2) mov si,0 mov ax, 3) mov di,0 mov ax, 下面三组指令也实现了相同的功能: 1) mov bx,0 mov ax, 2) mov si,0 mov ax, 3) mov di,0 mov ax, SI 和 DI 复制字符串到另一地址 更少代码的示例,Debug 分析过程…… 和 例: mov ax, 的含义 将一个内存单元的内容(字单元)送入ax寄存器,偏移地址为bx+si,段地址在ds中。 描述: (ax)=((ds)*16+(bx)+(si)) Debug 查看…… 和 数学描述: (ax)=((ds)*16+(si)+(idata)) 代码对比 使用上面原理操作多维数组 将每个单词的第一个字母改为大写字母~:) Debug 验证结果 多重循环转换数组中所有字母为大写 Debug 调试结果~:))) 不管有多少个内、外循环,都只有一个cx计数器。 上面代码是用寄存器暂存数据。 用内存暂存数据 将菜单中前4个字母大写,使用栈来存储数据 Debug 分析结果 [ Last edited by redtek on 2006-12-27 at 10:44 PM ] |
|
| 第75楼 redtek | 发表于 2006-12-28 12:12 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 数据处理
寄存器(reg)集合包括: ax,bx,cx,dx,ah,al,bh,bl,ch,cl,dh,dl,sp,bp,si,di; 段寄存器(sreg)集合包括:ds,ss,cs,es; 要处理的数据有多长? 1) 通过寄存器名指明要处理的数据尺寸。 2) 在没有寄存器名存在的情况下,用操作符 X ptr 指明内存单元的长度。 X 在汇编指令中可以为 word 或 bye。 mov word ptr ds:,1 inc word ptr 在没有寄存器参与的内存单元访问指令中,用 word ptr 或 byte ptr 显性地指明所要访问的内存单地长度是必要的。 否则CPU无法得知所要访问的单元是字单元还是字节单元。
寻址方式的缩合应用 更改内存中的数据 数据在内存中存放形式 代码如下 修改完成 很象结构体 按C风格描述 按C风格,用汇编语言重写上面操作数据的代码 在机器码中,上面不同书写的代码在机器码中只有一种表示 DIV 除法操作 1) 除数:有8位和16位两种 2) 被除数:默认放在AX或DX和AX中。 如果除数为8位,被除数则为16位。默认在AX中存放。 如果除数为16位,被除数则为32位,在DX和AX中存放。DX存高16位,AX存低16位。 3) 结果 如果除数为8位,则AL存放商,AH存放余数。 如果除数为16位数,则AX存放商,DX存放余数 格式: div reg div 内存单元 例: div byte ptr ds: 含义: (al)=(ax)/((ds)*16+0))商 (ah)=(ax)/(ds)*16+0))余数 div word ptr es: (ax)=/((es)*16+0) 商 (dx)=/((es)*16+0) 余数 div byte ptr (al)=(ax)/((ds)*16+(bx)+(si)+8) 商 (ah)=(ax)/(ds)*16+(bx)+(si)+8) 余数 div word ptr (ax)=/((ds)*16+(bx)+(si)+8) 商 (dx)=/((ds)*16+(bx)+(si)+8) 余数 计算 100001 / 100 100001(16)=186A1H 100(16)=64H 如果用 Debug 直接写汇编代码,一切都是16进制。 如果用 Masm 汇编代码写再编译,随便。 被除数是32位,那么计算除得的商与余数就必须(商16位、余数占16位),除数也占16位。 186A1H(被除数)的位低是:86A1H 、高位是:0001H Debug 直接汇编代码如下: 用 windows 计算器算 100001 / 100 = 1000.01 (十进制) 上面值做为验证之用~:) 商:1000 余数:01 它们的16进制表示: 商:03E8H 余数:0001H 商与余数各占16位,商在低位表示的寄存器中,余数在高位表示的寄存器中。 再看 Debug 结果数据:
红色标注表示:商 绿色标注表示:余数 ~:) Masm 汇编代码,求 1001 / 100 验证计算结果 AX=010A,结果正确~:) 商:0AH , 余数: 01H 伪指令 dd 定义dword(double word)-双字型数据。 双字型数据占 32 位。 如果汇编代码: dd 1 则16进制表示其所占用的空间: 00000001H 用 div 计算 data 段中第一个数据除以第二个数据后的结果,商存放在第3个数据的存储单元中。 商
DUP 操作符 它与 db,dw,dd等数据定义伪指令配合使用,用来进行数据的重复。 db 重重的次数 dup (重复的字节型数据) dw 重重的次数 dup (重复的字型数据) dd 重重的次数 dup (重复的双字型数据) 数据分布
寻址方式在结构化数据访问中的应用 [ Last edited by redtek on 2006-12-28 at 06:19 PM ] |
|
| 上一页 1 … 2 3 4 5 6 7 8 … 9 下一页 |
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |