




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
-.z.对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致阻碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩DEBUG,有时CRACK出一个小软件比完成一个程序更有成就感〔就像学电脑先玩游戏一样〕。*些高深的指令事实上只对有经历的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开场,你必须要先排除那些华美复杂的命令,将注意力集中在最重要的几个指令上〔CMPLOOPMOVJNZ……〕。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩〔用WINZIP、WINRAR…依次压迫,嘿嘿!〕教程。大言不惭的说,看通本文,你完全可以"不经意〞间在前辈或是后生卖弄一下DEBUG,很有成就感的,试试看!则――这个接下来呢?――Herewego!〔阅读时看不懂不要紧,下文必有分解〕因为汇编是通过CPU和内存跟硬件对话的,所以我们不得不先了解一下CPU和内存:〔关于数的进制问题在此不提〕CPU是可以执行电脑所有算术╱逻辑运算与根本I/O控制功能的一块芯片。一种汇编语言只能用于特定的CPU。也就是说,不同的CPU其汇编语言的指令语法亦不一样。个人电脑由1981年推出至今,其CPU开展过程为:8086→80286→80386→80486→PENTIUM→……,还有AMD、CYRI*等旁支。后面兼容前面CPU的功能,只不过多了些指令〔如多能奔腾的MM*指令集〕、增大了存放器〔如386的32位EA*〕、增多了存放器〔如486的FS〕。为确保汇编程序可以适用于各种机型,所以推荐使用8086汇编语言,其兼容性最正确。本文所提均为8086汇编语言。存放器〔Register〕是CPU内部的元件,所以在存放器之间的数据传送非常快。用途:1.可将存放器内的数据执行算术及逻辑运算。2.存于存放器内的地址可用来指向内存的*个位置,即寻址。3.可以用来读写数据到电脑的周边设备。8086有8个8位数据存放器,这些8位存放器可分别组成16位存放器:AH&AL=AX:累加存放器,常用于运算;BH&BL=BX:基址存放器,常用于地址索引;CH&CL=CX:计数存放器,常用于计数;DH&DL=DX:数据存放器,常用于数据传递。为了运用所有的内存空间,8086设定了四个段存放器,专门用来保存段地址:CS〔CodeSegment〕:代码段存放器;DS〔DataSegment〕:数据段存放器;SS〔StackSegment〕:堆栈段存放器;ES〔E*traSegment〕:附加段存放器。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段存放器CS,DS,SS来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS所指的64K内,这就是文件不得大于64K的原因。8086以内存做为战场,用存放器做为军事基地,以加速工作。除了前面所提的存放器外,还有一些特殊功能的存放器:IP〔IntructionPointer〕:指令指针存放器,与CS配合使用,可跟踪程序的执行过程;SP〔StackPointer〕:堆栈指针,与SS配合使用,可指向目前的堆栈位置。BP〔BasePointer〕:基址指针存放器,可用作SS的一个相对基址位置;SI〔SourceInde*〕:源变址存放器可用来存放相对于DS段之源变址指针;DI〔DestinationInde*〕:目的变址存放器,可用来存放相对于ES段之目的变址指针。还有一个标志存放器FR〔FlagRegister〕,有九个有意义的标志,将在下文用到时详细说明。内存是电脑运作中的关键局部,也是电脑在工作中储存信息的地方。内存组织有许多可存放数值的储存位置,叫"地址〞。8086地址总线有20位,所以CPU拥有达1M的寻址空间,这也是DOS的有效控制范围,而8086能做的运算仅限于处理16位数据,即只有0到64K,所以,必须用分段寻址才能控制整个内存地址。完整的20位地址可分成两部份:1.段基址(Segment):16位二进制数后面加上四个二进制0,即一个16进制0,变成20位二进制数,可设定1M中任何一个64K段,通常记做16位二进制数;2.偏移量(Offset):直接使用16位二进制数,指向段基址中的任何一个地址。如:2222〔段基址〕:3333〔偏移量〕,其实际的20位地址值为:25553。除了上述营养要充分吸收外,你还要知道什么是DOS、BIOS功能调用,简单的说,功能调用类似于WIN95API,相当于子程序。汇编写程序已经够要命了,如果不用MS、IBM的子程序,这日子真是没法过了〔关于功能调用详见"电脑爱好者"98年11期〕。编写汇编语言有两种主要的方法:1.使用MASM或TASM等编译器;2.使用除错程序DEBUG.。DEBUG其实并不能算是一个编译器,它的主要用途在于除错,即修正汇编程序中的错误。不过,也可以用来写短的汇编程序,尤其对初学者而言,DEBUG更是最正确的入门工具。因为DEBUG操作容易:只要键入DEBUG回车,A回车即可进展汇编,过程简单,而使用编译器时,必须用到文本编辑器、编译器本身、LINK以及E*E2BIN等程序,其中每一个程序都必须用到一系列相当复杂的命令才能工作,而且用编译器处理源程序,必须参加许多与指令语句无关的指示性语句,以供编译器识别,使用DEBUG可以防止一开场就碰到许多难以理解的程序行。DEBUG除了能够汇编程序之外,还可用来检查和修改内存位置、载入储存和执行程序、以及检查和修改存放器,换句话说,DEBUG是为了让我们接触硬件而设计的。〔8086常用指令用法将在每个汇编程序中讲解,限于篇幅,不可能将所有指令列出〕。DEBUG的的A命令可以汇编出简单的文件,所以DEBUG编写的程序一定要由地址100h〔文件要求〕开场才合法。FOLLOWME,SETPBYSETP〔步步回车〕:输入A100;从DS:100开场汇编
2.输入MOVDL,1;将数值01h装入DL存放器
3.输入MOVAH,2;将数值02h装入DL存放器
4.输入INT21;调用DOS21号中断2号功能,用来逐个显示装入DL的字符
5.输入INT20;调用DOS20号中断,终止程序,将控制权交回给DEBUG
6.请按Enter键
7.现在已将汇编语言程序放入内存中了,输入G(运行)
8.出现结果:输出一个符号。
ㄖ←输出结果其实不是它,因WORD97无法显示原结果,故找一赝品将就着。
Programterminatednormally我们可以用U命令将十六进制的机器码反汇编〔Unassemble〕成汇编指令。你将发现每一行右边的汇编指令就是被汇编成相应的机器码,而8086实际上就是以机器码来执行程序。
1.输入U100,106
1FED:0100B201MOVDL,01
1FED:0102B402MOVAH,02
1FED:0104CD21INT21
1FED:0106CD20INT20
DEBUG可以用R命令来查看、改变存放器内容。CS:IP存放器,保存了将执行指令地址。
1.输入R
A*=0000B*=0000C*=0000D*=0000SP=FFEEBP=0000SI=0000DI=0000
DS=1FEDES=1FEDSS=1FEDCS=1FEDIP=0100NVUPEIPLNZNAPONC
1FED:0100B201MOVDL,01当程序由DS:100开场执行,则终止程序时,DEBUG会自动将IP内容重新设定为100。当你要将此程序做成一个独立的可执行文件,则可以用N命令对该程序命名。但一定要为文件,否则无法以DEBUG载入。
输入NSMILE.;我们得告诉DEBUG程序长度:程序从100开场到106,故占用7
;字节。我们利用B*存放长度值高位局部,而以C*存放低位局部。
2.输入RB*;查看B*存放器的内容,本程序只有7个字节,故本步可省略
3.输入RC*;查看C*存放器的内容
4.输入7;程序的字节数
5.输入W;用W命令将该程序写入〔Write〕磁盘中修行至此,我们便可以真正接触8086汇编指令了。当我们写汇编语言程序的时候,通常不会直接将机器码放入内存中,而是打入一串助记符号〔MnemonicSymbols〕,这些符号比十六进制机器码更容易记住,此之谓汇编指令。助记符号,告诉CPU应执行何种运算。也就是说,助忆符号所构成的汇编语言是为人设计的,而机器语言是对PC设计的。现在,我们再来剖析一个可以将所有ASCII码显示出来的程序。
1.输入DEBUG
2.输入A100
3.输入MOVC*,0100;装入循环次数
MOVDL,00;装入第一个ASCII码,随后每次循环装入新码
MOVAH,02
INT21
INCDL;INC:递增指令,每次将数据存放器DL内的数值加1
LOOP0105;LOOP:循环指令,每执行一次LOOP,C*值减1,并跳
;到循环的起始地址105,直到C*为0,循环停顿
INT20
4.输入G即可显示所有ASCII码
当我们想任意显示字符串,如:UNDERSTAND?,则可以使用DOS21H号中断9H号功能。输入下行程序,存盘并执行看看:
1.输入A100
MOVD*,109;DS:D*=字符串的起始地址
MOVAH,9;DOS的09h功能调用
INT21;字符串输出
INT20
DB'UNDERSTAND?$';定义字符串在汇编语言中,有两种不同的指令:1.正规指令:如MOV等,是属于CPU的指令,用来告诉CPU在程序执行时应做些什么,所以它会以运算码〔OP-code〕的方式存入内存中;2.伪指令:如DB等,是属于DEBUG等编译器的指令,用来告诉编译器在编译时应做些什么。DB〔DefineByte〕指令用来告诉DEBUG将单引号内的所有ASCII码放入内存中。使用9H功能的字符串必须以$结尾。用D命令可用来查看DB伪指令将那些内容放入内存。
6.输入D100
1975:0100BA0901B409CD21CD-20756E6465727374!.underst
1975:0110616E64248B46F889-45048B4634006419and$.F..E..F4.d.
1975:012089450233C05E5FC9-C300C80400005756.E.3.^_WV
1975:01306BF80E81C7FE538B-DF8BC2E832FE0BC0kS2...
1975:0140740533C099EB178B-450CE8D4978BF089t.3E
1975:015056FE0BD074EC8B45-0803C68B56FE5E5FV...t..EV.^_
1975:0160C9C3C80200006BD8-0E81C3FE53895EFEkS.^.
1975:01708BC2E8FBFD0BC075-098B5EFE8B470CE8u..^..G..现在,我们来剖析另一个程序:由键盘输入任意字符串,然后显示出来。db20指示DEBUG保存20h个未用的内存空间供缓冲区使用。
输入A100
MOVD*,0116;DS:D*=缓冲区地址,由DB伪指令确定缓冲区地址
MOVAH,0A;0Ah号功能调用
INT21;键盘输入缓冲区
MOVDL,0A;由于功能Ah在每个字符串最后加一个归位码〔0Dh由Enter
MOVAH,02;产生〕,使光标自动回到输入行的最前端,为了使新输出的
INT21;字符串不会盖掉原来输入的字符串,所以利用功能2h加一
;个换行码(OAh),使得光标移到下一行的的最前端。
MOVD*,0118;装入字符串的起始位置
MOVAH,09;9h功能遇到$符号才会停顿输出,故字符串最后必须加上
INT21;$,否则9h功能会继续将内存中的无用数据胡乱显示出来
INT20
DB20;定义缓冲区
送你一句话:学汇编切忌心浮气燥。客套话就不讲了。工欲善其事,必先利其器。与其说DEBUG是编译器,倒不如说它是"直译器〞,DEBUG的A命令只可将一行汇编指令转成机器语言,且立刻执行。真正编译器〔MASM〕的运作是利用文本编辑器〔EDIT等〕将汇编指令建成一个独立且附加名为.ASM的文本文件,称源程序。它是MASM程序的输入局部。MASM将输入的ASM文件,编译成.OBJ文件,称为目标程序。OBJ文件仅包含有关程序各部份要载入何处及如何与其他程序合并的信息,无法直接载入内存执行。链结程序LINK则可将OBJ文件转换成可载入内存执行〔E*Ecute〕的E*E文件。还可以用E*E2BIN,将符合条件的E*E文件转成文件〔文件不但占用的内存最少,而且运行速度最快〕。
下面我们用MASM写一个与用DEBUG写的第一个程序功能一样的程序。
用EDIT编辑一个SMILE.ASM的源程序文件。
源程序DEBUG程序
prognamsegment
assumecs:prognam
org100hA100
movdl,1movdl,1
movah,2movah,2
int21hint21
int20hint20
prognamends
end比拟一下:1.因为MASM会将所有的数值假设为十进制,而DEBUG则只使用十六进制,所以在源程序中,我们必须在有关数字后加上代表进制的字母,如H代表十六进制,D代表十进制。假设是以字母开头的十六进制数字,还必须在字母前加个0,以表示它是数,如0AH。2.源程序增加五行表达:prognamsegment与prognamends是成对的,用来告诉MASM及LINK,此程序将放在一个称为PROGNAM(PROGramNAMe)的程序段内,其中段名〔PROGNAM〕可以任取,但其位置必须固定。assumecs:prognam必须在程序的开头,用来告诉编译器此程序所在段的位置放在CS存放器中。end用来告诉MASM,程序到此完毕,ORG100H作用相当于DEBUG的A100,从偏移量100开场汇编。文件的所有源程序都必须包含这五行,且必须依一样的次序及位置出现,这点东西记下就行,千篇一律。接着,我们用MASM编译SMILE.ASM。
输入MASMSMILE←不用打入附加名.ASM。
Microsoft(R)MacroAssemblerVersion5.10
Copyright(C)MicrosoftCorp1981,1988.Allrightsreserved.
Objectfilename[SMILE.OBJ]:←是否改动输出OBJ文件名,如不改就ENTER
Sourcelisting[NUL.LST]:←是否需要列表文件〔LST〕,不需要就ENTER
Cross-reference[NUL.CRF]:←是否需要对照文件〔CRF〕,不需要则ENTER
50162+403867Bytessymbolspacefree
0WarningErrors←警告错误,表示编译器对*些语句不理解,通常是输入错误。
0SevereErrors←严重错误,会造成程序无法执行,通常是语法构造错误。如果没有一个错误存在,即可生成OBJ文件。OBJ中包含的是编译后的二进制结果,它还无法被DOS载入内存中加以执行,必须加以链结〔Linking〕。以LINK将OBJ文件〔SMILE.OBJ〕链结成E*E文件〔SMILE.E*E〕时,。
1.输入LINKSMILE←不用附加名OBJ
Microsoft(R)OverlayLinkerVersion3.64
Copyright(C)MicrosoftCorp1981,1988.Allrightsreserved.
RunFile[SMILE.E*E]:←是否改动输出E*E文件名,如不改就ENTER
ListFile[NUL.MAP]:←是否需要列表文件〔MAP〕,不需要则ENTER
Libraries[.LIB]:←是否需要库文件,要就键入文件名,不要则ENTER
LINK:warningL4021:nostacksegment←由于文件不使用堆栈段,所以错误信息
←"nostacksegment"并不影响程序正常执行至此已经生成E*E文件,我们还须使用E*E2BIN将E*E文件〔SMILE.E*E〕,转换成文件〔SMILE.〕。输入E*E2BINSMILE产生BIN文件〔SMILE.BIN〕。其实BIN文件与文件是完全一样的,但由于DOS只认、E*E及BAT文件,所以BIN文件无法被正确执行,改名或直接输入E*E2BINSMILESMILE.即可。现在,磁盘上应该有SMILE.文件了,你只要在提示符号C:>下,直接输入文件名称SMILE,就可以执行这个程序了。你是否觉得用编译器产生程序的方法,比DEBUG麻烦多了!以小程序而言,确实是如此,但对于较大的程序,你就会发现其优点了。我们再将ASCII程序以编译器方式再做一次,看看有无差异。首先,用EDIT.建立ASCII.ASM文件。
prognamsegment;定义段
assumecs:prognam;把上面定义段的段基址放入CS
movc*,100h;装入循环次数
movdl,0;装入第一个ASCII码,随后每次循环装入新码
ne*t:movah,2
int21h
incdl;INC:递增指令,每次将数据存放器DL内的数值加1
loopne*t;循环指令,执行一次,C*减1,直到C*为0,循环停顿
int20h
prognamends;段终止
end;汇编终止
在汇编语言的源程序中,每一个程序行都包含三项元素:
start:movdl,1;装入第一个ASCII码,随后每次循环装入新码
标识符表达式注解在原始文件中加上注解可使程序更易理解,便于以后参考。每行注解以";〞与程序行别离。编译器对注解不予理会,注解的数据不会出现在OBJ、E*E或文件中。由于我们在写源程序时,并不知道每一程序行的地址,所以必须以符号名称来代表相对地址,称为"标识符〞。我们通常在适当行的适当位置上,键入标识符。标识符〔label〕最长可达31个字节,因此我们在程序中,尽量以简洁的文字做为标识符。现在,你可以将此ASCII.ASM文件编译成ASCII.了。1.MASMASCII,2.LINKASCII,3.E*E2BINASCIIASCII.。注意:当你以编译器汇编你设计的程序时,常会发生打字错误、标识符名称拼错、十六进制数少了h、逻辑错误等。汇编老手常给新人的忠告是:最好料到自己所写的程序一定会有些错误〔别人告诉我的〕;如果第一次执行程序后,就得到期望的结果,你最好还是在检查一遍,因为它可能是错的。原则上,只要大体的逻辑架构正确,查找程序中错误的过程,与写程序本身相比甚至更有意思。写大程序时,最好能分成许多模块,如此可使程序本身的目的较单纯,易于撰写与查错,另外也可让程序中不同部份之间的界限较清楚,节省编译的时间。如果读程序有读不懂的地方最好用纸笔记下有关存放器、内存等内容,在纸上慢慢比划,就豁然开朗了。下面我们将写一个能从键盘取得一个十进制的数值,并将其转换成十六进制数值而显示于屏幕上的"大程序〞。前言:要让8086执行这样的功能,我们必须先将此问题分解成一连串的步骤,称为程序规划。首先,以流程图的方式,来确保整个程序在逻辑上没有问题〔不用说了吧!什么语言都要有此步骤〕。这种模块化的规划方式,称之为"由上而下的程序规划〞。而在真正写程序时,却是从最小的单位模块〔子程序〕开场,当每个模块都完成之后,再合并成大程序;这种大处著眼,小处著手的方式称为"由下而上的程序设计〞。我们的第一个模块是BINIHE*,其主要用途是从8086的B*存放器中取出二进制数,并以十六进制方式显示在屏幕上。注意:子程序如不能独立运行,实属正常。
binihe*segment
assumecs:binihe*
movch,4;记录转换后的十六进制位数〔四位〕
rotate:movcl,4;利用CL当计数器,记录存放器数位移动次数
rolb*,cl;循环存放器B*的内容,以便依序处理4个十六进制数
moval,bl;把b*低八位bl内数据转移至al
andal,0fh;把无用位清零
addal,30h;把AL内数据加30H,并存入al
cmpal,3ah;与3ah比拟
jlprintit;小于3ah则转移
addal,7h;把AL内数据加30H,并存入al
printit:movdl,al;把ASCII码装入DL
movah,2
int21h
decch;ch减一,减到零时,零标志置1
jnzrotate;JNZ:当零标志未置1,则跳到指定地址。即:不等,则转移
int20h;从子程序退回主程序
binihe*ends
end利用循环左移指令ROL循环存放器B*(B*内容将由第二个子程序提供)的内容,以便依序处理4个十六进制数:1.利用CL当计数器,记录存放器移位的次数。2.将B*的第一个十六进制值移到最右边。利用AND〔逻辑"与〞运算:对应位都为1时,其结果为1,其余情况为零〕把不要的部份清零,得到结果:先将BL值存入AL中,再利用AND以0Fh〔00001111〕将AL的左边四位清零。由于0到9的ASCII码为30h到39h,而A到F之ASCII码为41h到46h,连续了7h,所以得到结果:假设AL之内容小于3Ah,则AL值只加30h,否则AL再加7h。ADD指令会将两个表达式相加,其结果存于左边表达式内。标志存放器〔FlagRegister〕是一个单独的十六位存放器,有9个标志位,*些汇编指令〔大部份是涉及比拟、算术或逻辑运算的指令〕执行时,会将相关标志位置1或清0,常碰到的标志位有零标志〔ZF〕、符号标志〔SF〕、溢出标志〔OF〕和进位标志〔CF〕。标志位保存了*个指令执行后对它的影响,可用其他相关指令,查出标志的状态,根据状态产生动作。CMP指令很像减法,是将两个表达式的值相减,但存放器或内存的内容并未改变,只是相对的标志位发生改变而已:假设AL值小于3Ah,则正负号标志位会置0,反之则置1。JL指令可解释为:小于就转移到指定位置,大于、等于则向下执行。CMP和JG、JL等条件转移指令一起使用,可以形成程序的分支构造,是写汇编程序常用技巧。第二个模块DECIBIN用来接收键盘打入的十进制数,并将它转换成二进制数放于B*存放器中,供模块1BINIHE*使用。
decibinsegment
assumecs:decibin
movb*,0;B*清零
newchar:movah,1;
int21h;读一个键盘输入符号入al,并显示
subal,30h;al减去30H,结果存于al中,完成ASCII码转二进制码
jle*it;小于零则转移
cmpal,9d
jge*it;左>右则转移
cbw;8位al转换成16位a*
*chga*,b*;互换a*和b*内数据
movc*,10d;十进制数10入c*
mulc*;表达式的值与a*内容相乘,并将结果存于a*
*chga*,b*
addb*,a*
jmpnewchar;无条件转移
e*it:int20;回主程序
decibinends
end
CBW实际结果是:假设AL中的值为正,则AH填入00h;反之,则AH填入FFh。*CHG常用于需要暂时保存*个存放器中的内容时。
当然,还得一个子程序〔CRLF〕使后显示的十六进制数不会盖掉先输入的十进制数。
crlfsegment
assumecs:crlf
movdl,0dh;回车的ASCII码0DH入DL
movah,2
int21h
movdl,0ah;换行的ASSII码0AH入AH
movah,2
int21h
int20;回主程序
crlfends
end现在我们就可以将BINIHE*、DECIBIN及CRLF等模块合并成一个大程序了。首先,我们要将这三个模块子程序略加改动。然后,再写一段程序来调用每一个子程序。
crlfprocnear;
movdl,0dh
movah,2
int21h
movdl,0ah
movah,2
int21h
ret
crlfendp类似SEGMENT与ENDS的伪指令,PROC与ENDP也是成对出现,用来识别并定义一个程序。其实,PROC真正的作用只是告诉编译器:所调用的程序是属于近程〔NEAR〕或远程〔FAR〕。一般的程序是由DEBUG直接调用的,所以用INT20返回,用CALL指令所调用的程序则改用返回指令RET,RET会把控制权转移到栈顶所指的地址,而该地址是由调用此程序的CALL指令所放入的。
各模块都搞定了,然后我们把子程序组合起来就大功告成
decihe*segment;主程序
assumecs:decihe*
org100h
movc*,4;循环次数入c*;由于子程序要用到c*,故子程序要将c*入栈
repeat:calldecibin;调用十进制转二进制子程序
callcrlf;调用添加回、换行符子程序
callbinihe*;调用二进制转十六进制并显示子程序
callcrlf
looprepeat;循环4次,可连续运算4次
movah,4ch;调用DOS21号中断4c号功能,退出程序,作用跟INT20H
int21H;一样,但适用面更广,INT20H退不出时,试一下它
decibinprocnearpushc*;将c*压入堆栈,;
┇e*it:popc*;将c*复原;retdecibinendpbinihe*procnearpushc*
┇popc*retbinihe*endpcrlfprocnear
pushc*
┇popc*retcrlfendpdecihe*endsendCALL指令用来调用子程序,并将控制权转移到子程序地址,同时将CALL的下行一指令地址定为返回地址,并压入堆栈中。CALL可分为近程〔NEAR〕及远程〔FAR〕两种:1.NEAR:IP的内容被压入堆栈中,用于程序与程序在同一段中。2.FAR:CS、IP存放器的内容依次压入堆栈中,用于程序与程序在不同段中。PUSH、POP又是一对指令用于将存放器内容压入、弹出,用来保护存放器数据,子程序调用中运用较多。堆栈指针有个"后进先出〞原则,像PUSHA*,PUSHB*…POPB*,POPA*这样才能作到保护数据丝毫不差。汇编语言超浓缩教程到这要告一段落了,希望能奠定你独立设计的根底。而更多更好的技巧则全依赖你平时的积累了。祝你成功!分类:汇编学习嵌入式开发黑客技术上一篇:如何学习汇编语言下一篇:一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率收藏到网摘:汇编教程(1):如何学习汇编2021-11-0115:43
想想我自己玩电脑也是不少时间了,也经常在各大论坛灌水,得到过很多人的帮助。但是非常遗憾的事一直都没有为别人奉献过什么,现在我有点时间所以写了几篇关于汇编的文章,我以后还会继续更新。路线是:先写点16位汇编-32位汇编-解密知识-外挂制作。希望大家关注,同时多给点意见,在下将非常感谢,同时希望大家多多回复不要让帖子沉下去。希望多多支持
如果大家有什么问题可以给我发Email:424608qq.
我将尽全力帮助你解答问题!
写这篇文章〔我准备把他写成一个系列〕,我想讲述如何从零开场学汇编语言程序设计,请千万相信汇编其实是很简单的,只要自己努力一定是可以学会的。可能由于我的技术(编程和写作)也很不到家在很多方面都写的不是很好甚至是胡说八道(但愿你不会这样认为)。如果你对此有什么意见可以给我发Email:424608qq.给我我将竭尽全力的回复每一封同时希望大家多给我提提意见,让我把文章写的更好。。!这篇文章里不会有太多技术方面的东西,我想在这章先和大家一起探讨如何学习汇编的问题,也许有些内容让你觉得我很啰唆。那是以为我为了照顾大局部的读者所以写的比拟详细。。请大家多支持我,看了之后多给我意见。如果没有意外我会坚持每个礼拜发表一篇。今天写的是第一章,只是个引子,还没具体涉及到编程。罗云彬说的好啊,学汇编就像千军万马过独木桥,能够坚持到最后的很少。这个不禁让我想起了高考啊。汇编这东西如果你真的学精通的话可以让计算机做很多别人不能够做的事情,因此很多人都想学习汇编。掌握这方面技术,对自身的提高确实有好处。你可以通过反汇编别人的程序跟踪别人的软件,了解别人的编程思路。通过了解别人的程序思路,使自己写出更加好的程序。而且写病毒,木马和外挂等等的一些软件~~~都必须用汇编才能够写的漂亮。研究汇编还有助于掌握一些系统底层知识,系统底层知识绝对是构造起大型软件的坚实根底。许多程序开展,都经历了这一锻炼过程的。而大多数人可能认为汇编是一门高深的学问。很难学,我前几天在网上拿了个软件给我朋友用。他问我用什么写的,我说用汇编。。他不信以为汇编根本就写不出强大复杂的软件,其实这都是老皇历了(现在的汇编其实我感觉和C差不多都是调用windowsAPI来编程)。造成这种原因我觉得是以前在dos下面用汇编来写程序太麻烦,所以给人的感觉就成了很复杂,(以前在dos下汇编没有很多API可以调用)就将汇编神话了,造成初学者在心理上就成认了汇编很难学的〞事实〞其实不是这样现在其他编程语言可以做的比方C,用汇编做起来也不是很麻烦。再一方面由于学习资料比拟匮乏学。初学者一般不知从何下手,由于没方向,花费了大量时间和精力,走了不少弯路。这里我就给想学汇编的指下学习方向(根据我自己的学习经历)。在学汇编前,最好先掌握一门高级语言编程,这样再学汇编应容易些,如果你学校或者在其他地方学了C语言的学起来就比拟轻松了,很多书上都是用C语言程序做范例来讲解的,如果你没有学也没有关系这里我给你推荐个视频:<<尚学堂科技java系列视频教程>>,这个教程可比那些什么什么大学跟这课本念PPT的好多了,你或者会问我为什么学汇编要去看java的视频啊,这里我只是推荐你去看下他视频的前3章,也就算根底知识,这在所有的程序设计语言里面都适用,看完了再学习汇编坡度就不会则陡了。看完视频我想再向大家介绍几本书都是中国人写的(我觉得国人计算机方面的著作就算汇编比拟有出席拉)一本是王爽写的<<汇编语言>>和罗云彬写的windows环境下32位汇编语言程序设计,这2本书在学习汇编的人心中地位都非常高现在都出了第2版了,而且网上都有电子版,google下就能找到。其他还有一些书比方:温冬蝉,沈美明:清华大学,"IBMPC汇编语言程序设计教程",。【美】KipR。Irvine著,温玉杰等译:"Intel汇编语言程序设计"〔第四版〕,都是比拟经典的,如果有时机可以看看!!学习汇编要多动手,不要只看书和书上的例子,有条件就把例子弄到电脑上试一试,如果成功了,不要快乐,你的工作只完成了一半,把例子改一改,按你的意思,想想改了之后的结果,与上机对照一下,你会有收获的。写汇编程序难免会出错,老一辈的人都还在讲解着dubug的使用,其实现在windows环境下的汇编调试器已经非常的完善了,我平时一般是用RadASM里面自带的调试器,他已经可以给我解决大局部由于编程粗心而引起的错误,还有一些是逻辑错误我一般用ollydbg进展调试,这里我再给大家推荐个编辑器RadASM,这是一个非常棒的汇编IDE编程环境掌握他的使用可以让安心的写汇编程序而不用把心思在记忆复杂的一些编译指令上,我准备写篇RadASM的教程,但是现在还没有动笔。现在比拟好的讲解RadASM可能是jhkdiy写的Win32汇编开发环境介绍和RadAsm简明教程学习汇编其实很累的,需花费大量的时间,而且经常会遇到很多的问题,资料又比拟匮乏。这时你可能有点想退却,其实你不要着急,只要你认真学习,成功就在眼前。没有人是生来就什么都会的,如果你有问题,就大胆的去问你周围的人。而且现在网上也有很多的专门讨论汇编的站点比拟好的应该是aogo的汇编小站和罗云彬的编程乐园,学汇编的秘诀就是勤奋+执着!记住并能做到这两点,你会变得很优秀的。不管你学汇编是出于什么目的,如果你在学习汇编的过程中如果遇到了问题可以发给我探讨,我非常的欢送是:424608163.。同时在学习汇编的时候如果突然觉得学的很痛苦,可以在看雪学院下点东西玩玩解密,培养培养下兴趣也未尝不可啊!多在机子上试试底层的东西,如bios调用,IO操作,对显卡,硬盘的控制。那样你会体会到学习汇编语言的快乐。总之要记得想学会汇编,你需要自立自强,以及自学能力。现在开场吧……
请注明出自暗组技术论坛.darkst./bbs/汇编语言(2):如何学习汇编2021-11-0115:44
准备提笔写的时候好似不知道怎么下笔啊,毕竟以前我都没有写过技术方面的文章,怕自己技术不够让高手笑话,又怕表达不清楚自己的意思.但是心一横死就死吧!在上一篇如何学习汇编中没有给大家扯太多技术话题,但是我觉得那也是非常重要的,学习什么事有了信心就成功了一半,所以还希望大家继续坚决要把汇编学好的思想,要相信自己汇编是很简单的,我们通过自己的努力一定可以把汇编学好则让我们开场今天的话题…..今天主要扯点计算机的工作方式,因为汇编是面向机器的语言,所以非常有必要了解下计算机的构造,CPU的工作方式.这里我假设你只有一点点最根本的电脑根底啊,最好自己去弄懂那个什么进制转换的,我觉得特麻烦,不过却也比拟简单..我这里就不和大家扯了自己了解下~~则既然假设你没有什么电脑知识就会显得有些啰唆,高手别见笑啊!说到汇编语言啊,就扯远拉,远到哪里呢,嗯很远,汇编语言和机器语言是很亲密的,所以要聊下汇编语言那就不得不又扯下机器语言了,^_^.真远啊!!机器语言什么叫机器语言呢,机器语言就是一些机器指令的集合拉,也就是一些二进制的数字什么010010的,这就是机器指令,计算机呢可以把这些010010什么的转变为上下电平,使计算机的电子器件收到驱动,进展运算..嗯,搞的好似很复杂似的,其实简单理解就是计算机也有一门语言(机器语言)就像我们的汉语一样,我们汉语的构成呢是由字来构成的,机器语言(也就是电脑自己的语言,就是一些01001什么的来构成的.当初我理解的时候就想啊,机器语言不是人创造的么,为什么不教他学汉语啊要教他学什么01001的则麻烦^_^.呵呵其实现在很多人都在做着这样的努力呢,诶~~又扯远了.给大家扯了机器语言的那就再给大家扯一下计算机吧,你有跟朋友去过电脑城装过电脑吗"或者见过别人把电脑机箱翻开后里面的情况吗"对里面有一个大风扇,大风扇下面知道是什么吗"那是CPU就是电脑的心脏,那家伙就像我们脑袋一样是指挥部.其实我们见到的那CPU叫微处理器,是它控制着电脑的显卡啊,声卡什么的,当然我们不能够直接去控制这些东西那些玩意不听我们的,但是他们的指挥官(CPU)听我们,我们编程的任务就是指挥CPU(嗯,你可以把这想象成一场战争)去控制显卡显示图像,声卡发声.是不是很兴奋,可是我要跟你说的是他们的指挥官(CPU)是个莽夫特别讨厌学习国家的语言(这个和我倒是有些类似啊).所以我们想要和CPU沟通就要学习他的语言,可是他的语言实在是太难学了(有点向英语则难学^_^)所以我不准备去学习他的语言,同时我也不建议你去学它的语言,那你要问我怎么办拉,嘿嘿很好办,你看过和布什谈话的时候是怎么谈的吗"对拉有翻译,毛主席说人人都是平等的,胡主席可以请翻译,我们也可以~~~~我们的翻译的就是汇编,汇编是个好同志啊,他帮我们把指令翻译成很长很长的0101001,从此我们就离开了机器语言的怀抱,而用汇编来控制CPU拉,这是什么,这是世界的进步啊,是不是又感觉这世界又美好了一些!!汇编语言则,我们现在已经理解了汇编语言和机器语言的一样和区别了,要说一样的话他们都好似是4个汉字,区别就是前2个字不同,倒下一片~~~~~~",其实汇编和机器语言在我理解是没有什么区别的,汇编只是把机器语言的010010对应的翻译了一下,就像我学英语一样,老是喜欢做硬式翻译,所以此时此刻我不得不再打击你一下,因为汇编只是硬式翻译了下机器语言,所以造成了汇编的指令过多,和过于复杂了.当然后来为了解决这个问题又出了C语言对吧,你不会想当叛徒去投靠C吧,晕,*三丰说过,千万不能够当叛徒,这不,现在的32位汇编就有宏汇编,搞的和C都差不多了,所以你也别想着要跑C那里去,现在我们只要学习下DOS下的汇编理解了那些指令的用处,到时候我们在windows下面写程序的时候都有很多宏可以调用了..汇编语言的组成则我们现在把机器语言扯完了,(其实我还想再扯一会的).但是怕你不满意!!下面就是汇编闪亮登场了,你也许会问我汇编长什么样子呢""这不好说啊,但是我可以肯定的是他绝对没有我帅^_^…其实汇编不能够说长什么样子,应该说汇编由什么东西构成呢,则我告诉你汇编是由一些指令比方你看着头晕的mov啊什么的,还有就是伪指令了,伪指令就是些段标记啊什么,现在不知道没有关系,到时候我再跟你扯..存储器(内存)现在我假设你已经把汇编指令学完了,则你肯定是命令计算机执行几条指令对吧,理论上说的过去,但是现在还有个小问题就是..你在什么地方给计算机发布命令呢"计算机可不是很随便的人啊,计算机很死板死板到什么程度呢,它只能够在内存(存储器)中承受我们的指令.其他地方…sorry不行.所以我们必须把我们的指令放到内存里面让CPU来读取和执行,所以知道内存的作用了吧,很重要吧,则我们当然要了解下CPU是如何来读取我执行我们的指令的对吧..所以我们的学习环节里面又多了个,了解CPU是如何在内存中读取指令和写入指令..则到底CPU是如何去读取指令呢,是这样的,CPU把内存划分成一个一个的单元,单元里边的编号是从0开场的,比方有128个存储单元,则第一个就是0最后一个就是127,你现在肯定想问拉,那一个存储单元可以存多少信息呢""计算机把一个2进制位称为一个比特(bit)8个就是一个字节了,(Byte)实际上现在的电脑啊它的内存是大的不得了的,我们只有了解这个概念就成,比方我现在写文章这台的电脑就有512M内存,则换算下来是多少呢"1KB=1024B(Byte)1MB=1024KB1GB=1024MB1TB=1024GB你可能要问了,我这是不是在讲硬盘啊,硬盘上面才用多少个G啊这样标示啊,其实内存和硬盘是一样的,他们的计量单位都是按照上面那些公式来的.存储单元刚刚给大家扯到,内存被分为多个存储单元,存储单元是从0开场编号.你可能有疑问为什么要编号呢,这里就可以给你答复了,这就向一条街啊,你找一户人家肯定不好找对吧,但是给他们的房子都弄个编号那就好找了..其实CPU读数据就向找人一样啊,根据门牌号(存储单元编号)这样找就非常快拉.地址总线既然说到了编号啊,就给大家聊点编号的问题吧,CPU本是有限啊,只能够指定特定多的存储单元,为什么啊,这个就是由于CPU的地址总线的限制了,比方啊我们的**是18位的,当我们国家的人口啊超过18为数字能够容纳的范围的话是无法标示的对吧(不过估计目前是无法到达这个数字的,这都是方案生育搞的好啊),则现在是CPU有多少地址总线的话就只能够对特定多的内存进展寻址,如果再多出来的内存是没有用的,我们假设CPU有10根地址总线则我们来看下他的寻址情况,在电子计算机中,一根导线可以传送的稳定状态只有2种,0和1则10根地址总线可以标示的范围为,2的10次方个,最小就是0,则最大就是1023了.所以可以得出结论,一个CPU有N跟地址线,则可以寻址的范围为2的N次方个内存单元.数据总线既然聊了关于存储器(内存)的则多,不妨再聊点比拟有趣的事情,聊什么呢,聊点关于CPU读取指令的问题,首先我想向大家提个问题,比方我现在在内存中有1000条指令啊,CPU来读取这些指令的时候可以一次全部读完吗"这个问题啊,据我所知啊我们现在用的CPU是没有方法一次全部读完的,则它怎么办呢,你也想到了,就是分屡次来读取对吧.则问题又来了CPU一次可以读取多少条指令呢"这要看CPU的数据总线的宽度了,8086的CPU数据总线宽度为16位,是16位2进制的数据比方现在传送89D9H8086CPU就可以一次传送完,如果是89D898则这个数字16位就标示不完了,所以要分两次来传送.你看到这里我不得不佩服你的勇气,你是一个精神可嘉的人,虽然我写着很累,但是相信你看着也不轻松啊,诶..主要是因为我文采不好写的很烂,让人不大容易明白,其实这些东西都是概念性的东西,我这人最讨厌概念性的东西了,所以我学汇编的时候也是囫囵吞枣就过去了,所以现在给大家讲起来也底气缺乏..不过没有关系这些概念性的东西没有弄懂也没有关系,了解下就成了,等你到时候把汇编学个入门后再倒回来看就会获益匪浅的.回忆下我们吹了什么东西,机器语言,汇编语言明白了吗"存储器(内存)的作用明白了吗"存储单元和地址总线还有数据总线这些明白了吗"如果明白了就过关了,如果没有诶~~~~不是你有问题就是我有问题了..这段终于给大家吹完了,我也松了一口气,以后的扯淡应该会更加轻松些.所以别紧*.下一篇可能要过几天了,这几天比拟忙啊!下一篇就给大家真刀实枪的干了,我们就要接触汇编指令了,期待吧!请多多支持我的blog,你们的支持是我最大的动力..有动力马才跑的快啊!汇编教程(3):存放器CPU工作原理①2021-11-0115:54
你真的弄懂了汇编语言根底""真的吗"如果是则就继续今天的话题啊!!在对CPU读取指令方面有了一个感性的了解后,我们就应该学学存放器了,存放器可以说是汇编代码里面必然存在的东西,不然这汇编程序就没法写了,那存放器是什么呢"CPU到底是怎么样操作存放器的呢""…
现在的孩子真幸福啊,今天我一个18岁的朋友来象我请教如何配置电脑的问题,呵呵,想象一下啊我18岁都在做些什么呢"不过非常不幸的是,我那朋友想买电脑来打完美世界.这不得不让我吃惊啊,现在的孩子虽然得到的东西多了,也不知道他们是否知道珍惜啊!!好了不跟大家扯这些家常了,我本来文采就不怎么好,写这个教程权当自娱自乐啊,希望高手要求不要放太高,但是有错误是一定要提的!上次写的那篇汇编根底收到了不少朋友的反应,他们说我取的名字不好,不应该叫汇编精通啊(前两篇这个教程叫汇编精通),和我这样的写作风格不相配,想想也是哦,所以改成了现在这个名字.还有不少朋友给我提了很珍贵的意见,其中有位朋友说我写的跑题了..其实我写这个教程不打算教会你汇编,我也没有那个本领,我只是想大家对汇编有个感性的认识..或者是你在阅读其他书籍的时候有什么概念上的东西觉得干涩的,我给大家做个感性的介绍而已,我的想法是:如果你想学习汇编,你手里起码得有几本书吧,比方我在如何学习汇编那篇文章中给大家介绍那本王爽写的汇编语言就非常不错,我就是靠这本书带入门的,所以希望阁下学习汇编还是以书本为主啊,我本来技术就有限.甚至连一些概念上的东西弄错了都不知道,惭愧惭愧啊..上节课给大家介绍了机器语言和汇编语言,并且对CPU读取指令有了一个感性的认识,如果你没有读懂的话请给我发送或者参看王爽写的汇编语言..其实那篇文章说的东西你不懂也没有关系,我觉得和写汇编程序关系不大,特别是写win32汇编程序..既然如此就让我们了解今天的话题CPU的工作原理..CPU的工作原理其实CPU从不亲自去作显卡显示图像,声卡发出声音这些事情,而是CPU在自己的逻辑存储器(这是假想中的,这个操作对我们是透明的)地址空间里通过控制总线进展操作,那些外部器件自己在逻辑存储器里面找块地方让CPU分个地址..这个说起来好似比拟拗口啊,没有关系如果你不懂也关系不大,如果觉得我讲的不太明白可以参考王爽汇编对于一个汇编程序员来说不必要深入的了解这些东西,我们在写程序的时候主要是和存放器打交道我们通过操作存放器来到达控制CPU的目的.所以不了解以上讲的问题不是很大的..存放器:既然我们用汇编写程序主要打交道的是存放器,则我们有必要深入的了解下存放器了,存放器是什么呢"它其实和内存是一样的东西,只是更加快而已,所以别被他吓倒,则有多少个存放器呢"我可以非常难过的告诉你,存放器的个数非常多,诶当初我就是看到这个才放弃学习汇编的,不过后来有幸看到了王爽的汇编语言后,才觉察原来存放器也不过如此啊,我知道你现在想深入的了解存放器,但是请别急慢慢来,,我们先了解4个存放器A*B*C*D*..这4个我们用的最多了,我知道你现在又非常的想了解存放器到底有什么用,但是请听我说,你还需要具备一点东西,来伙计,我再给你介绍2条常见的汇编指令,非常容易理解:mov指令,add指令..它们的用法是这样的:mova*,19
将19送入A*
A*=19adda*,18
将存放器A*的值+18
A*=A*+18简单吧,学过高级语言的优势就出来咯,如果你还不懂高级语言赶紧去看下尚学堂那个视频啊!那来考虑下我们在高级语言里面这样一段代码inta=10;intb=20;intc;c=a+b;我们用汇编该怎么来表示呢""我想应该是这样的mova*,10movb*,20addc*,a*addc*,b*明白了吧,存放器是什么玩意,现在不嫌弃存放器的个数多了吧,也不觉得存放器多有什么问题了吧,毛主席说:代码就能够说明一切问题啊,这应该是有道理的..则到底有多少存放器呢,总共只有4个A*,B*C*D*..但是对我们的编程来说一点问题也没有有了4个就够了~~~..在8086以前的CPU都是8位的..8086是16位的机器上面的那些存放器都是16位的(明白什么叫16位了吧),那以前8086以前的CPU呢怎么办呢"intel向了个折中的方法,就是把这些16位的存放器再进展分家,就分成了高8位和低8位比方A*就分为AHALB*就分为BHBLC*就分为CHCLD*就分为DHDL这里H和L的意思分别表示High和Low好理解了吧,其实它们的用法也是一样的,我们就挑A*来讲讲,比方现在有一个数字43E4储存在A*中则AH的值为43,AL为E4为什么呢"intel的CPU是把数据按照高位到低位排列的所以AH(高8位)就存储了43,AL(低8位)就存储了E4,就则简单,由上我们也可以看出CPU可以处理的数据只有2种,一种是字(word占16位)一种是字节(byte8位),一个字存放在16位存放器中,这个字的高位字节和低位字节自然就存储在这个存放器的高8位和低8位了..比方A*=3454H则自然的AH=34HAL=54H同时我们又可以把AH和AL当作单独的两个存放器来使用它们都互不影响的!如:AH=42H则AL还是为54H但是A*却改变了A*=4254H,则存放器的内容就这些了,只是有些细节要注意下,请看代码:mova*,8F35Hadda*,4E34Hadda*,9F45H则现在A*的值为多少呢"你可能会认为是17CAF,但是我告诉你A*=7CAF,为什么呢如果一个值超过了它所能表示的范围,则它将把进位丢弃(不是真的丢弃,但是我们现在可以这样认为)同样的事情发生在8位存放器上,请看:moval,8FHaddal,4EHaddal,45H则AL的值是22,它同样丧失别以为他会进位到AH或者其他地方,这里我们如果进展的8位运算CPU就只认识8位存放器,其他的不管,所以以下这些指令都是错误的:mova*,bl
‘把16位和8一起用是错的movbh,a*
‘把8位和16为一起用也是错的mova*,20000000
‘把一个大于存放器的值赋给存放器也是错的addal,10000
‘将一个大于8位的数据加到8位存放器也是错的嗯,终于完了,这是一场攻坚战啊,学汇编和学C不同如果上来就HelloWorld的话估计大局部人都的晕,所以我们还是要先打下根底啊,虽然现在还是纸上谈兵,但是我们毕竟已经接触到了汇编指令了,再过两结课我们就可以上机写写指令了,但是现在还不行,先好好体会下..接下来我们还要讲下CPU是怎么给出物理地址..好好体会,如果觉得我讲的哪里不对和不明白一定要告诉我!!我建议你学习的时候结合下书本,效果肯定要好很多的.汇编教程4:存放器CPU工作原理②2021-11-0115:55
最近在网上看了长篇小说<<疯狂的程序员>>。。嗯不错不错,看来这做程序员的人还大多有些相似的,不过每个人却还是有些不同的,就象我。。诶到现在还是一无所有,人财两空啊~~~~~~命苦不能怪政府。。上一篇存放器CPU工作原理1,给大家介绍了几个存放器,那几个存放器因为是最常用的所以也叫通用存放器,相信大家对这存放器还是有了一个感性的认识了,但是CPU不能够只访问存放器的,它要做更多的事情,比方读取内存。这应该说是CPU的根本功能之一吧,所以我们不了解下CPU访问内存的方法确实有点那个啊。。。既然这样我们还是有必要了解下的。。。。。CPU要访问内存它必须给出内存单元的地址,同时这些单元都是一维线性的。每一个内存单元都有一个唯一的地址。。这在前面的章节有所提及,则CPU是怎么样给出内存单元的地址呢""想要了解这个问题,我们还得看看CPU的构造。。我们通常说的8086CPU是16位的,则这个16位代表了什么概念呢"这个嘛。。概括起来的讲啊主要是这几点。。
存放器一次最多只能处理16位的数据。
存放器的最大宽度为16位
存放器和运算器之间的通路为16位但是问题就来了,8086有20位地址总线(20位地址总线的寻址能力就有1M了),而CPU内部只能够处理16位的数据那改怎么办呢""这个问题嘛,当然不可以浪费了地址总线对吧。。~~如果是地址总线也改成16位的则我们的CPU寻址能力就只有64K了,那可是天壤之别啊。。当然的想个方法对不。。别人说intel里面的人都是天才,从这方面说的话还是有些道理的。。他们想到了在CPU内部做一个加法器来进展合成一个20位的物理地址。。则合成过程是怎么样的呢""嗯,,,好的请听我细细道来。首先CPU中的相关部件(这个部件我们马上要提到)提供2个16位的地址,然后送入一个叫地址加法器的部件,然后地址加法器再把两个地址合成为一个20位物理地址。。则现在问题又来了对吧。。。他是怎么样合成物理地址的呢""没有关系这里有个公式。。。套公式总是比想问题简单些的。。。额。合成地址的规则是这样的:
物理地址=段地址*16+偏移地址。。
毛主席说过,实践才是硬道理啊,给大家套个公式就明白了,比方现在CPU要访问内存地址单元124C8H的内存单元,则我们就可以让段地址为1240H,然后让偏移地址为00C8H,套用公式就比拟简单了:
124C8H=1240H*16+00C8H
注意拉,这里别弄错了,这里我们讨论的数据都是16进制的,所以*16只是把小数点移动了一位而已,嗯。。是不是已经感觉到了16进制的好处了。。当你在感慨16进制是多么好之余有没有想过。。我刚刚写的那公式里面讲了什么。段。。段地址。。什么的!这个段地址又是什么概念呢""千万别以为是一段一段的地址啊!,其实内存里面是绝对没有分段的,分段只是来自CPU自己。其实分段以后是有好处的,这样我们就可以把一些连续的内存当作一个段来使用,套用上面的公式,段地址不变。。只是改动偏移地址。。哈哈这样就方便多了。我们知道偏移地址也是16位的,则一个段最长呢也只能有64KB而已,明白了吗"以为偏移地址只能够表示64KB的内存而已。。。前面我们讲到了〞CPU的相关部件提供两个地址〞,这么一句话。。那到底是什么东西在提供段地址呢""又是什么东西提供偏移地址呢"",这又不得不让我想到了存放器,回忆我们前面学习的(应该还不至于忘记吧)4个通用存放器,则是不是CPU内部只有则多存放器呢"不是的。。呐。我这里就再给你说一个存放器。这个存放器就是专门用来放段地址的,它就是CS存放器,不过好似叫存放器就俗了些,不可以表达出它和其他那些存放器的区别来,因为那些存放器都是放一般性数据,,这CS存放器可就不同咯。。所以又给它改个名字,就叫段存放器吧。。这样理解应该比拟好理解吧!!现在还有个小问题,我们有了一个叫CS的段存放器,,那还得有一个放偏移地址的存放器啊,这次倒霉的就是CPU中一个叫IP的存放器(嗯,别和IP地址的IP弄混了)。。啊,原来是这样啊。现在是万事俱备只欠东风啊。。就让我们来套用这个公式吧。。
物理地址=CS*16+IP
就这样,给出了物理地址,事实上当你为CS为什么不叫E*或者其他的名字的时候,我得告诉你一个天大的秘密:
在8086的CPU上,任意时刻,设CS中的内容为M,IP的内容为N,则8086将从内存:
M*16+N单元开场执行。。
你可能不以为然呐,这有什么了不起啊,我跟你说这就错了,有了这玩意可以玩的事情可就多了。。你想啊我们想让CPU执行一条指令我们要怎么办呢"想到了吧,嘿嘿。。让我值得快乐的是,我比你先想到~~~~我们只要设M*16+N的值为我们想要的内存单元地址那不就得了吗"对的,确实是这样。。
在任意时刻CPU将CS:IP指向的内容当作指令执行
为了让你有个更感性的认识我非常有必要举个例子,这是毛主席说的,实践才是硬道理啊,比方我在内存20000-20003处有条指令,则我们想让这条指令执行一下该这么办呢"我想应该是这样的
1。让CS:IP的值指向20000处
2。读取并执行指令,同时IP值要加3
我说的第一点可能比拟好理解了,可为什么要加3呢,其实是这样的,你想想啊。。。CPU从20000处开场读取指令,读取到指令后就会返回,然后呢执行,CPU在执行完了这条指令后当然知道这条指令是占几个字节,这里是3个字节。。所以CPU就会把IP的值加3。。。嗯,明白了吧,原来是这样啊。
知识这东西啊,确实是好东西。当然你得先把它学会对吧。。现在让我们回想一下,那个电脑为什么在一按电源就会呼啦啦自动执行指令。。则我们由此可以判断出,一定是有什么东西在修改着CS:IP的值对吧。。则事实上是这样的。。
8086在加点启动后(或者重启了电脑)CS:IP的值被分别设置为CS=F000H,IP=FFFFH也就是说CPU在启动的时候从FFFF0H单元开场执行第一条指令,有趣吧。。所以我们可以得出结论:
想要让指令执行必须让CS:IP指向它,反过来,一条指令如果被执行了,则CS:IP一定指向过它。。是不是已经按耐不住了,忍不住想写几条指令给CPU执行了""事实上我是一个不喜欢调人胃口的人,但是此时此刻我不得不提醒你,你还记得mov,add。指令吗"不会则快就把这两条指令忘了吧,如果忘记了。则你应该再回头看看存放器(CPU工作原理1),如果你还记得则就比拟简单了,例如我们还是在内存20000-20003处有条指令,则我们可以这样写代码:
movcs,2000H
movip,0H
如果你这样写的话,是要出错的,因为intel公司不给你这样干,这样写的指令是错误的。。你可能想问下为什么不行,则我可以给你,你打去intel问下就清楚了,则既然intel不给我们这样干,他总的提供让我们怎么修改CS和IP的值的方法吧,则我可以明确的告诉你,方法是有的,就是用另外一条指令,它就是jmp,使用方法:同时修改CS和IP的值:jmp段地址:偏移地址
jmp1000:2只修改IP的值:jmp*一合法存放器
jmpa*‘这条指令执行的效果和movip,0H的效果差不多
如果你看到了这里,并且前面的教程你都看了,并且明白了,则我不得不佩服你的勇气,与毅力,好好努力,相信自己一定可以把汇编学好的。相信你看到这里也开场心里甜了吧,很多奥秘开场向你解开,我当初就是学到这里的时候想,我一定要把汇编学下去,并且要学好。。相信你也是一样,下一篇我就要给大家将debug的使用了,虽然那东西简陋但是还是有必要了解下的。。因为它简单,学起来方便。。OK今天就到这里吧,晚上2点了!汇编教程5:debug的使用2021-11-0115:56嗯,这次距离上次文章发布快两个礼拜了,今天我终于痛下决心了。要再写一篇。写到一半,好友"冰横〞,来向我介绍黑莓手机,,黑莓??什么是黑莓手机。诶!看来啊,落后拉。。后来查下资料才发现,这东西确实好啊,又廉价,功能又多。。有时间挑一个。然后在写这篇文章的时候,要找一个屏幕截图的软件,我用的是SangIt这个软件我可是用了好几年了6.0就开场用了,现在都9.0了。非常不错。在WP里面上传的时候弄了好几次都没有成功,不过最后还是成功拉!废话少说,开场今天的话题:debug的使用上次我们讲了CPU给出物理地址的方法、和介绍了2个段存放器CS和IP。虽然我已经写了好几篇了,但是还没有涉及到任何的编程知识,这在学习高级语言里面是不敢想象的,学高级语言就是好啊,比方C。哈哈上来就写"helloworld〞,汇编可不行,,写完这篇,我们还不能写出"HelloWorld〞,还要下几篇才可以,不过别泄气。通用存放器那章都挺过来了,这两篇不难。本来我是想直接和大家讲"RadASM〞想想还是作罢,还是讲讲"debug〞吧,让大家了解下计算机内部的原理。实际上你以后在编程工作中根本就用不到"debug〞,至少我是很少用到,我都是用"RadAsm〞里面集成的调试器,直观,方便。所以这章也不用死记,只要了解原理就成。"debug〞是什么呢?debug是一个软件,是一个调试其他软件的软件,既然是软件,当然要启动拉,在windows2000/*p下启动可以这样,[开场]-[运行]-[cmd]。翻开命令行窗口,然后输入命令[debug],这样就启动了程序debug是古老的命令行方式运作,命令繁多,一下介绍怕消化不完,则我们只学习几个常用的。-R
查看,改变存放器的值。-D
查看内存中的内容-E
改写内存中的内容-U
将内存中的机器指令翻译为汇编指令-T
执行一条汇编指令-A
以汇编的指令的格式在内存中写入一条汇编指令这就是我们最常用的debug指令了。这样罗列出来给大家看,非常的不直观。。我们就来做几个实例虽然我个人非常不喜欢用图片来讲解计算机的原理性的东西,但是不可否认,这样更容易让人理解:-R:查看和修改存放器的值:我们已经学过6个存放器了,4个通用的,2个段存放器。。上面是在命令行里面显示的信息,,非常简单、你在自己电脑上试试就可以了,告诉你一个小密码,这个命令是系统自带的,所以别问我哪里下载〔这个软件在MS-DOS的时候就是系统自带了,所以现在的系统里面都有这个软件。如果你看不明白请在自己的电脑中试验下,实在不明白请看王爽"汇编语言",首先最上面是输入了-R命令,然后显示出了很多存放器的值,有几个我们是认识的,有几个我们还不认识,不过没有关系,我们会在以后的时间介绍,现在就先不管了,反正记得这是显示存放器的值就是拉,左下角这里显示的CA12:0100你仔细看看就明白了,刚好对应CS:IP的值对吧。旁边的ADDDH[DI+48]这就是当前CS:IP指向地址的指令。同样的右下角还有个DS:0048=00这个也不用深究,现在不用了解。。命令就是这样,很简单,自己试验试验就直观了,如果要改变一个存放器的值可以这样:输入命令-R接着要修改的存放器,然后回车,就输入想要修改存放器的值就成,然后你要记得举一反三,修改其他存放器的值方法也是一样的,包括CS:IP存放器。所以说是非常简单的。。-R命令:查看内存中的内容:我们可以用d段地址:偏移地址的方式查看,使用方法如下:输入命令后,默认是显示从你输入的物理地址开场128个内存单元的内容,右边全是点…的这里是该内存单元内容所对应的ASCII码。如果你嫌弃它给你显示的内存单元少了或者多了,比方现在我们要显示1000:0-1000:23内存单元的内容该怎么做呢?我们可以试试这样:d:1000:023。这样就把1000:0-1000:23内存单元的内容全部显示出来了,一个不多,一个不少。这里就不截图了,自己试试。-E命令:改写内存单元的内容:这个比拟简单,截图一看你就明白了:非常简单吧,我们先用d命令查看了1000:0处的内容,然后用e命令修改内存单元的内容,总共修改了11个从43开场到32完毕。当然你也可以写入ASCII码值,道理和写入数字是一样的,不过记得字符串要加冒号〞"。是英文的冒号。-U命令:查看内存中该地址对应的汇编指令:可以看出来,这条命令是非常简单的,这条命令和-D很像,-D是查看内存中的ASCII码,-U是查看对应的汇编指令。非常简单。所以看到这里你就应该明白,在内存中执行指令和数据是没有区别的,关键是CPU如何解释了,如果你让CS:IP指向它,则这个地方就是执行指令,如果你让~~~,呵呵那个还没有讲呢,下次再讲。-A命令:以汇编的形式在内存中写入指令:使用方法也是非常简单:我们首先用-A在2000:0处写入了3条指令,然后用-U查看了2000:0-2000:10的汇编指令,结果当然是显示我们刚刚写入的指令了,所以说非常简单。看也看了,写也写了,追究是为了执行,所以我们来看看如何执行汇编指令。-T命令:执行一条指令,如果没有给出CS:IP,则就执行默认的CS:IP处的指令:T命令也是非常简单的,上图我们是先用-R命令查看了存放器的值,然后用-R修改了CS和IP的值,然后用-A在2000:0处写入了一条指令,最后用-T执行了一下,注意看A*的值,是不是加1了,非常简单吧。。到这
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 车间现场管理课件
- 2025年全国助残日专题知识竞赛考试题库50题(含答案)
- 2025执业兽医考试题库参考附参考答案详解(b卷)
- 2025年机械设备安全防护技术标准考核试卷(附答案)
- 殡仪馆考试题及答案
- 安徽大学电路分析基础期末试卷及答案
- 2025年疟疾防治知识培训考试题及答案
- 2025年应急救援员工作人员岗位职业技能及安全基本知识考试题库及答案
- 第十四章 全等三角形 有关证明题 专题练(含答案)初中数学人教版(2024)八年级上册
- 车辆驾驶知识课件
- 派出所签订治安调解协议书范文
- 情境领导力培训课件
- DBJ41T 277-2023 装配式钢结构集成楼盖应用技术规程 河南省工程建设标准(住建厅版)
- 飞灰螯合物运输服务方案
- 中建三局社招在线测评题
- 研究生学术表达能力培养智慧树知到答案2024年西安建筑科技大学、清华大学、同济大学、山东大学、河北工程大学、《环境工程》英文版和《环境工程》编辑部
- 玉米种植风险评估与管理
- 2024-2030年中国自动涂胶机行业市场发展趋势与前景展望战略分析报告
- DL∕T 2582.1-2022 水电站公用辅助设备运行规程 第1部分:油系统
- TCNPA - 景区玻璃栈道建设规范
- 股权估值协议书模板
评论
0/150
提交评论