第七章: 学过C语言的都知道,在C语言中,也有逻辑与运算和逻辑或运算。汇编语言当然也有 and 和or就是 我是这么理解and和or and的是逻辑与运算,相当于两人谈感情,0代表假,1代表真,那么必须两人同时为 真也就是1的时间,结果才能为真,如果一个人为假就是零,那么结果也就是0 如: mov al,11111111b and al,00000000b 那么结果就是:00000000 or是逻辑或运算,就是一厢情愿,只要有一方愿意付出,愿意为真,那么结果就能为真 如: mov al,11111111b or al,00000000b 那么结果就是:11111111b ASCII码: 呵呵,这个和摩斯电码很像,喜欢无线电技术的朋友会有所体感,一个指定的值代表一个英文字母,就想电视中,嘀嘀 嘀 滴滴 滴滴 呵呵!这个是无线电台相互交流时所采用的一种编码,电脑也有,我们常用的如ASCLL码,当然还有其他很多。 ASCII表。百度一下,有很大这种表,不需要大家死记,但最好能记得其中的规律。 当你打开一个win下得文本编辑器时,按下键盘的A键,屏幕上就会显示出A,具体是 怎么实现的呢?如下: 1.电脑开机,打开编辑器,按下键盘的A 2.按下以后,键盘会把这个信息传送给计算机,计算机内部通过ASCLL码进行编码,将对应值61H存储在内存空间中, 3.编辑器,从相应的内存空间取出这个值61H,送入显卡的显存当中,此事工作在文本模式下得显卡,就会利用ASCLL码进行解码,就会把61H转换为字符A 4.此时显卡驱动显示器,将A的图像显示在屏幕上,我们也就能看到 结论:大写A在ASCLL码中对应的是61H,注意这是十六进制的61. 关于其他ASCLL码值,请大家自行下载ASCLL表进行查看 以字符形式给出数据 形式为:‘...’单引号,注意是英文的单引号 如:db‘ABCD’ 还不懂存储单元转换的,看日志揭秘系列的单讲。 打下这个程序: assume cs:qq,ds:ww (把qq,ww分别和寄存器CS,DS扯上关系) ww segment (ww段开始) db'abcd' (定义数据,把abcd对应的ASCLL码放入地址空间) db'ABCD' (同上) ww ends (ww段结束) qq segment (qq段开始) start: mov al,'a' (start定义程序入口,mov...意思把a的ASCLL值值放入寄存器al中) mov bl,'b' (同上) mov ax,4c00h(和一面一句,以后解释) int 21h qq ends (qq段结束) end start (程序结束,这个start和前面的staet对应) 大家可以载入debug中查看寄存器变化和相应地址空间的值。 待续... [bx+idata] 我们之前学过[bx]这个用法,他得段寄存器是ds,[bx]是他得偏移地址 例如: mov cx,[bx+100] 意思就是:把段地址为ds,偏移地址为bx+100的这个内存单元的数据送人cx中 逻辑表达就是ds*16+[bx]+100 运用这种方法,处理大小写转换的问题: 程序如下: assume cs:qq,ds:ee ee segment db 'FisHc' db 'LiNuX' ee ends qq segment start:mov ax,ee mov ds,ax mov bx,0 mov cx,5 s:mov al,[bx] and al,11011111b mov [bx],al mov al,[bx+5] or al,00100000b mov [bx+5],al inc bx loop s mov ax,4c00h int 21h qq ends end start si和di这两个寄存器,和bx寄存器功能相近,作为偏移地址时,他们的段地址都默认在ds中存放 如:mov bx,1 mov al,[bx+100] mov si,1 mov al,[si+100] 功能一样! 唯一不同的是,bx可以分为bl和bh两个8位寄存器,而si和di不能分成两个8位寄存器 书上7.2,把wlcome to masm 复制到他后面的数据区中, 我们先用[bx+idata]的方法来写,一次复制1字节 assume cs:qq,ds:ee ee segment db 'welcome to masm!' db '...............' ee ends qq segment start:mov ax,ee mov ds,ax mov bx,0 mov cx,16 s:mov al,[bx] mov [bx+16],al inc bx loop s mov ax,4c00h int 21h qq ends end start 一次复制2字节: assume cs:qq,ds:ee ee segment db 'welcome to masm!' db '...............' ee ends qq segment start:mov ax,ee mov ds,ax mov bx,0 mov cx,8 s:mov ax,[bx] mov [bx+16],ax add bx,2 loop s mov ax,4c00h int 21h qq ends end start 用si和di一次复制两个字: assume cs:qq,ds:ee ee segment db 'welcome to masm!' db '...............' ee ends qq segment start:mov ax,ee mov ds,ax mov cx,8 mov di,0 mov si,16 s:mov ax,[di] mov [si],ax add di,2 add si,2 loop s mov ax,4c00h int 21h qq ends end start 用si和di一次性复制一个字节: assume cs:qq,ds:ee ee segment db 'welcome to masm!' db '...............' ee ends qq segment start:mov ax,ee mov ds,ax mov cx,16 mov di,0 mov si,16 s:mov al,[di] mov [si],al inc di inc si loop s mov ax,4c00h int 21h qq ends end start 其实第七章注重一个灵活 如: [bx] [idata] [bx+idata] [bx+si] [si+bx+idata] 把 db '1.fishc..' db '2.linux..' db '3.unix...' db '4.windows' 首字母设置为大写: 代码如下: assume cs:qq,ds:ee ee segment db '1.fishc..' db '2.linux..' db '3.unix...' db '4.windows' ee ends qq segment start:mov ax,ee mov ds,ax mov bx,0 mov cx,4 s:mov al,[bx+2] and al,11011111b mov [bx+2],al add bx,9 loop s mov ax,4c00h int 21h qq ends end start 把 db '1.fishc..' db '2.linux..' db '3.unix...' db '4.windows' 所有字母设置为大写: 代码如下: assume cs:qq,ds:ee,ss:tt ee segment db 'dll' db 'exe' db 'dos' db 'win' ee ends tt segment db '......' tt ends qq segment start:mov ax,ee mov ds,ax mov ax,tt mov ss,ax mov sp,12 mov bx,0 mov cx,4 s1: push cx mov si,0 mov cx,3 s:mov al,[bx+si] and al,11011111b mov [bx+si],al inc si loop s add bx,4 pop cx loop s1 mov ax,4c00h int 21h qq ends end start 双层循环,多想想就明白了 最后一例: 把 db '1.fishc..' db '2.linux..' db '3.hacker...' db '4.windows' 把前四个字母设置为大写: 代码如下: assume cs:qq,ds:ee,ss:tt ee segment db '1.linux..' db '2.hacker.' db '3.windows' ee ends tt segment db '..........' tt ends qq segment start: mov ax,tt mov ss,ax mov sp,20 mov ax,ee mov ds,ax mov bx,0 mov cx,3 s: push cx mov si,0 mov cx,4 s1:mov al,[bx+si+2] and al,11011111b mov [bx+si+2],al inc si loop s1 add bx,9 pop cx loop s mov ax,4c00h int 21h qq ends end start (第七章完)第八章开始 首先是寄存器了,这里我们统计下之前所学的寄存器 首先四个:ax,bx,cx,dx, si,di,sp,ip,(bp),(pws) cs,ds,ss,(es) 其中:ax,bx,cx,dx,这四个可分为高低8位寄存器 如ah,al.... 其中cx 用来计算循环次数 bx一般当做偏移地址来说时,段地址在ds中 其中cs,ds,ss,es这四个为段寄存器 cs和ip为组合, 定义指令指针 ss和sp为组合, 定义栈 ds和bx,si,di组合,定义数据 关于es以后再说 bp下面说 pws以后再说 其中si,di与bx功能相似,作为偏移地址时,段地址都在ds中 不一样的是不能向bx一样可以划分为单独的两个8位寄存器 十四个寄存器中,唯一没有接触过的是:es段寄存器,pws寄存器 bp寄存器 说了这么说,就介绍下bp寄存器 bp寄存器,实际上和sp很相似,默认段地址都在ss中,BP可以间 接寻址寄存器而SP不能以外,其余的功能基本相同 如: mov ax,[bp] 就等于: ax=ss*16+(bp) 关于,bx,bp,si,di四个寄存器的配合 很多人晕,我是这样记的: 假设: bx和bp是两个男人,像我一样帅!呵呵,bx是我本人,bp就是你 了,他们名字的姓分别是bx姓ds bp姓ss si和di是两个女孩 很漂亮是亲姐妹,比如si是丁丁(人名),di是斜阳(人名),等 下封ID了... idata呢,就是小三了,像谁呢?你猜 一共5个人哈!记好! 根据我多年对易术天圆地方的研究!以及我多年的物理学经验,终 于得出一个结论:正负相吸,相同排斥的原理! 男女搭配的常规的四种搭配方式: [bx+si] [bx+di] 分别是:我和丁丁,我和斜阳 [bp+si] [bp+di] 分别是:你和丁丁,你和斜阳 当然,如果想搞小三的话,那可以加上idata,甲鱼(人名)常常 [bp+si+idata...] 多少个idata,谁知道呢??? 如: [bx+si+idata] 那这样就是,我和丁丁,外加小三.... 这种三人关 系还是可以的,我喜欢.... 你有钱的话,还可以多找几个小三,像甲鱼一样: [bx+si+idata+idata+...] 注意:绝不允许两个男人娶一个老婆,如: [bx+bp+si] 如,我和甲鱼和丁丁, 这样甲鱼是肯定不会愿意的 ,所以甲鱼只好走了,就剩我和丁丁,如:[bx+di] 当然这个时间 我还可以找个小三 ,如[bx+si+idata] 但是不能找斜阳了,不然就乱伦了...那就是[bx+si+di] 这样绝对不 行 还有就是连同小三我们五个人都单身一辈子,都单身一辈可以5个 单独出现,所以说: 亲!你是不是经常男女搭配啊! 亲!你是不是经常乱伦啊! 亲!你是不是经常同性恋啊! 亲!你是不是经常包小三啊! 亲!你是不是经常单身啊! 有木有??? 还有就是si和di不能一起,因为乱伦了! 注意:si可以单独和idata在一起,哎!这个关系怎么可以?设计 CPU的人啊!伤不起... 最后讨论下生出孩子的问题,主要是孩子姓什么? 注意一点: [bp+idata] [bp+di+idata] [bp+si] 很多人认为,bp段地址在ss,di或者si段地址在ds 这样是错误的! 只要bp出现,那就是统一段地址在ss中 这样理解: bp和bx说了是男人,si和di是女人, 夫唱妇随,孩子出生肯定跟随bp的姓了,那就是段地址在ss idata是小三! 呵呵,肯定也是男的是bp就跟ss,是dx就跟ds 如果小三和si与di在一起了,那就跟si和di的姓,也是ds 说下数据处理和数据有关的方面 首先cpu处理数据,一般不关心数据值是多少,而是关心数据所在 位置,一般有三种操作,读,写,运行 一般数据在三个位置: 内存地址 如:mov ax,[bx]或mov ax,[bx+2] cpu内部,如寄存器中,指令缓冲器... mov ax,bx或者mov ax,1 端口 暂时不说 数据进行运算时,一般不需要指定数据运算的单位,如字还是字节 那是因为很多运算使用了寄存器 如:mov ax,bx 默认就是字运算 如mov ax,1122h 注意:mov ax,12h 也是字运算,不要看只有12h就以为是字节运算 其实编译器当0012h mov al,bl 默认是字节运算 如 mov al,22h push和pop默认是字运算 如果在没有指定寄存器的情况下,不指定运算单位,就是要出错的 程序如下: 假设数据: ds:0 11 22 00 00.... 我们修改11为33,就是 33 22 00 00... 原来程序如下: assume cs:qq,ds:ee ee segment db 11h,22h ee ends qq segment start: mov ax,ee mov ds,ax mov bx,0 mov [bx],33h mov ax,4c00h int 21h qq ends end start 这样的话,结果是 ds:0 33 00 00 00 我们虽然修改了11,但同时也把22给修改了 因为此时没有出现寄存器,所以cpu就认为是字运算了 ,如果我们要单独修改11的话,那就用一条新指定 XX ptr 解析:xx可以是word或者byte... 如字运算: mov word ptr[bx],33h 如字节运算:mov byte ptr[bx],33h 这样的话,我们改进上面的程序,把mov [bx],33h 这一句修改为:mov byte ptr[bx],33h 程序结果如下: ds:0 33 22 00 00 这样就做到没有修改到22这个数据! 关于寻址方式加定义处理数据单位的综合因为: 我就写了个最简单的例子,没有用到循环和别的,就是让大家 更明了 assume cs:qq,ds:ee ee segment db'IBM' db'100' db'PDF' db'in' ee ends qq segment start: mov ax,ee mov ds,ax mov bx,0 mov byte ptr[bx+03h],'0' mov byte ptr[bx+04h],'1' mov byte ptr[bx+05h],'0' mov byte ptr[bx+06h],'d' mov byte ptr[bx+07h],'o' mov byte ptr[bx+08h],'c' 只修改一个字节 mov word ptr[bx+09h],'hh' 同时修改1个字 mov ax,4c00h int 21h qq ends end start 好了,第八章上半部分就说的这里! 第八章: DIV命令 除法命令 说下我们之前学过的运算 add 加sub减inc自加1div除 了解基本除法运算 9/2=4...1 9是被除数 2是除数 4是商 1是余数 在8086汇编中,除数可能有8位与16位两种 除数为8位时,被除数为16位,默认放在ax寄存器中 商则放在al中,余数放在ah中 例: div byte ptr [bx] 商al=(ax)/(ds*16+bx) 余ah=(ax)/(ds*16+bx) 如果除数为16位时,被除数为32位,默认放在ax和dx中, 其中bx存放高16位,ax存放低16位 商则放在ax中,余数则放在dx中 例: div word ptr [bx+si+6] 商ax=(dx*10000H+ax)/(ds*16+bx+si+6) 余dx=(dx*10000H+ax)/(ds*16+bx+si+6) 这里的10000H解析下: 如果32位数据为: AABBCCDD 那么AABB放在bx寄存器中 CCDD放在ax寄存器中 那么AABB*10000H时,也就是等于AABB0000 这个时间加上ax的值,那就是AABBCCDD 注意,一定要拿word ptr或者byte ptr指明是字节 还是字操作,也就是8位还是16位 举个例子 1000/101=9...101 程序如下: assume cs:qq,ds:ee ee segment db 65h ;65h即等于十进制101 ee ends qq segment start: mov ax,ee mov ds,ax mov ax,3E8h ;3E8h即等于十进制1000 mov bx,0 div byte ptr [bx] mov ax,4c00h int 21h qq ends end start 结果:ax=5B09 其中al=09即是商 ,十进制也是9 ah=5B即是余数 5Bh即十进制101 伪指令dd 其实前面我们说过了, db定义字节 8位 dw定义字 16位 dd定义双字 32位 dup这个命令很有用,大家在使用一段干净内存空间时 可以用它来定义 dup功能: XX y dup(a,b,c) 其中XX可以是dd,dw,db... y即是重复的次数 括号内部的a,b,c即是要重复的内容 如 db 3 dup(11,22) 执行后,相当于 db 11,22,11,22,11,22 关于实验7,我用了一个笨方法下了出来,虽然笨,但是几乎用到 了前面的所有的知识 我把代码写下来 assume cs:qq,ds:ee ee segment db '1991','1992','1993','1994','1995','1996' dd 16,22,382,1356,8000,5937000 dw 3,7,9,13,38,30000,17800 ee ends ;qq段开始 qq segment start: mov ax,ee mov ds,ax mov ax,1000h mov ss,ax ;年份计算 mov bp,0 mov bx,0 mov si,0 mov cx,6 s: mov es,cx mov cx,4 s1: mov word ptr ax,[bx] mov word ptr [bp+si],ax inc bx inc bp loop s1 mov cx,es add si,12 loop s ;中间空格 mov bp,0 mov cx,6 s2: mov byte ptr [bp+4],0 add bp,16 loop s2 ;收入计算 mov cx,6 mov bx,18h mov si,0 mov bp,0 s3: mov es,cx mov cx,2 s4: mov word ptr ax,[bx] mov word ptr [bp+si+5],ax add bx,2 add bp,2 loop s4 mov cx,es add si,12 loop s3 ;中间空格 mov bp,0 mov cx,6 s5: mov byte ptr [bp+9],0 add bp,16 loop s5 ;雇员数计算 mov cx,6 mov bx,30h mov si,0 mov bp,0 s6: mov es,cx mov cx,1 s7: mov ax,[bx] mov [bp+si+10],ax add bx,2 inc bp loop s7 mov cx,es add si,15 loop s6 ;中间空格 mov bp,0 mov cx,6 s8: mov byte ptr [bp+12],0 add bp,16 loop s8 ;最后的空格 mov bp,0 mov cx,6 s9: mov byte ptr [bp+15],0 add bp,16 loop s9 ;除法运算,商保存偏移OD处,余保存0E处 mov bp,0 mov cx,6 mov si,0 ps: mov bx,0 mov ax,[bp+si+5] mov dx,[bp+si+7] div word ptr [si+bp+10] mov [bp+si+13],ax mov [bp+si+14],dx add si,16 loop ps ;结束 mov ax,4c00h int 21h qq ends end start 书上原题,答案是这样的: assume cs:code,ds:data,es:table data segment db '1975','1976','1977','1978','1979','1980','1981','1982','1983' db '1984','1985','1986','1987','1988','1989','1990','1991','1992' db '1993','1994','1995' dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514 dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000 dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226 dw 11452,14430,15257,17800 data ends table segment db 21 dup ('year summ ne ?? ') table ends code segment start: mov ax,data mov ds,ax mov ax,table mov es,ax mov bx,0 mov si,0 mov di,0 mov cx,21 s: mov ax,[bx] mov es:[si],ax mov ax,[bx].2 mov es:[si].2,ax mov ax,[bx].84 mov es:[si].5,ax mov dx,[bx].86 mov es:[si].7,dx div word ptr ds:[di].168 mov es:[si].13,ax mov ax,[di].168 mov es:[si].10,ax add di,2 add bx,4 add si,16 loop s mov ax,4c00h int 21h code ends end start OK 第八章算是结束了,下面就是第九种跳转了 呵呵!破解的必备! 未完...看一楼......
|
本帖被以下淘专辑推荐:
- · 学习汇编|主题: 2, 订阅: 4
- · 我的土墙|主题: 12, 订阅: 1
- · 收帖|主题: 2, 订阅: 0
|