asm2

1.       为了以后的方便,我们定义了一个描述符号(),例(AX)表示急促器AX中的内容。

注意,()中的内容可以有三种 (寄存器名) (段寄存器名) (内存单元的物理地址)

2.我们约定,用idata表示常量,如mov ax [0],中的[0],就可以看做是形式[idata]

3 inc bx  是指bx 寄存器中的值需要加一。即自增指令

4Loop语句的用法,它必然是一种有关循环的指令那个,一种经典的代码形式:

Mov cx,11

S: add ax,ax

Loop S           其中S是语句编号,S代表一种地址,这个地址是add ax,ax这条命令语句的首地址。

CPU执行loop s的时候,执行了两步操作:

一,(cx)=(cx)-1

二,检查(cx) 若等于零,则继续向下执行

            若不等于零,则执行标号S处的指令语句。

5.如此可以总结循环功能的三个要点:

  A    CX里面放循环次数

  B    LOOP指令中标号所标识的地址要在前面

C    要循环指令的程序段要放在标号Sloop语句之间

6.规定:在汇编源程序中,数据不能以字母开头必须以数字开头,所以对于09FFF可以直接写,大于9FFF的数必须前边加0,即0A28DH

7 debug命令来跟踪程序的运行,如果想一步就完成多步的运行,则可以用G命令。

   g 0012   表示debug执行此命令后,CS0012之前的代码段指令被一次性执行。

8P命令除了可以进行执行跳转的指令即int 21之外,还可以用来一次性执行所有的循环,直至(CX=0。而不用一步步地总用T来但不执行。

9Debug和编译器 对于指令mov ax,[0]的理解和解释是不同的。Debug理解正常,但编译器会将其理解为mov ax,0

   对此,我们可以用debug来试验。一是直接用A命令来写代码,二是编写汇编程序,用U命令来直接查看汇编命令或者编译连接为.exe 再用debug来追踪这个可执行文件 debug 1.exe.

10.为了应对第九题这样一个伟大的错误,我们在汇编编程的时候,可以用一下两个方法来解决:

    一,用BX来作为立即数这样的偏移地址的载体,编译器是承认的。

        mov ax,[bx]  编译器认为是访问内存单元而不是BX中的内容。

       二.将段寄存器显化。mov ax,ds:[0]

11.我们如何将N个内存单元中的数据(八位)累加到一个16位寄存器中?有两种方法。

  一是(dx)=(dx)+八位数据  错误:数据的位数不匹配

  二是(dl)=(dl)+八位数据   缺陷:有可能造成数据不准确,因为会有进位产生超界。

  目前解决此问题的方法就是借助一个中介:一个16位的通用寄存器

mov al,(内存单元)

mov ah,0

mov dx,ax 这样就解决了上述两个问题。

12.对于变量X(比如访问一段连续内存时的偏移地址),我们可以用一个寄存器来充当。递增的话可以用 格式为         inc 充当变量的寄存器                pause120

13. 默认情况下,访问内存单元时,偏移地址就在BX中,所以有mov ax,[bx] 而此时数据的段地址就默认在dx中。

14.关于在实模式(纯DOS)下和保护模式下运行DOS的问题,实模式就是指没有任何保护措施下运行,也允许修改重要的内部信息。而保护模式下,当外界试图对重要信息所在段进行修改时,系统会阻止。出现如下提示:

15.我们是在操作系统下进行编程的,所以,对于一切我们可以利用的资源都是操纵系统给我们分配的,包括内存。而不应该自己任意指定内存写入等。因为我们并不知道重要的代码或数据在内存的什么位置。我们必须学会使用操作系统为我们分配的内存。

但是,我们也应该知道,我们用的是汇编语言,应该尽量去实现直接操作硬件进行编程的理想。

    现在的操作系统已经发展的很发达,将CPU保护模式所提供的功能都已经严格管理了。

所以,我们必须需要一段完全安全的内存单元,供给我们进行编程。这段就是0:200h-0:300h

256个字节长度的内存,我们约定,这段内存不存放系统重要的代码或数据。可以用D命令查看,如果内存中的内容都是0,则我们便可以对这段内存进行任意操作。

16.表示段超越前缀的用处:当从一段内存复制内容到另一段内存时进行复制操纵时,当两段内存的起始地址相差超过64KB时。。。    参考P124

17.mov 指令支持从内存单元到内存单元的移动吗?在源程序中,我们看到的的当数据从一个内存单元到另一个内存单元移动时,是借助了中介:寄存器。

18.add ax,cs:[bx]这条指令可以在你不知道段地址的情况下,将当前的指令复制在目的内存中。

19 dw是什么意思?是定义字型数据的意思,即define word

20.我们知道可执行文件包括程序以及描述信息。程序来自于源程序中的汇编指令和所定义的数据,描述信息来自于编译、连接程序对源程序中伪指令等相关信息的处理。

关于end指令,它不仅通知了编译的结束也提供了程序的入口信息。参考P128

这样的信息存在于.exe文件中,这样CPU根据这样的信息来设置CSIP

  对于汇编程序,我们一般的正确格式就是用代码段用start 后面用end start此时,代码段、数据段和栈段这三个段的位置我们可以任意放置。

如果没有start的话,只有当把代码段放在最前面时,程序才可以正确执行

21.我们说如果源程序中定义了N个字型数据,dw 1h,2h,3h,4h,…….

也表明是开辟了N个字型内存单元,这段空间内的数据依次是1h,2h,3h,4h,…

这两种结果是一样的。

22.第一个比较像样的汇编程序P131,它是将代码、数据和代码放在了各自不同的段中,由于段名表示的是此段的段地址,所以程序中出现了   mov ax,段名   这种格式。

     在编写汇编程序时,在代码段开始的时候,我们是应该做好初始化工作的包括对数据段、栈段、代码段等的初始化。即将各段的标号赋值给相应的段寄存器。此时CPU才知道了各自段的对应关系。

    并且在此时,比如对于数据段我们使数据段标号data,不能直接这样写mov ds,data

因为编译器将data解释为立即数,而8086是不允许将立即数直接赋值给段寄存器的。而应该这样 mov ax,data     mov ds,ax…

23.and指令作用就是 使得某些特定位归,其他位保持原来的数据。

  or 指令作用就是  使得某些特定位归,其他位保持原来的数值。

24  C语言中,字符是单引号,字符串是双引号。’a’   “unix”

    但汇编语言中字符和字符串都是单引号  mov ax,’a’  db ‘unix’

25.汇编语言中的字母的大小写:xX的区别之处就是ASCII码,小写的第五位是1,大写的第五位是0。所以进行大小写转换时,我们就可以用and or指令  p143

26  P145揭示了汇编语言和C语言的某种相通之处。

    就是表示数组的方式   C a[4]

                      汇编中  2[si]                idata[bx]

27.在程序中我们是可以通过16位寄存器来作为中介来进行内存之间数据的传送的。也 就是说命令mov ax,[bx]  mov ax,[si]  mov ax,[di] 等都是成立且正确的,他们表示传送的是字单元,即一次传送两个字节。

至此,我们也可以知道这样一点:8086不支持内存单元间数据的直接传送。

28  bx是通用寄存器,可以作为变址寄存器。  

以下两个跟BX的作用类似:    Si源变址寄存器  di 目的变址寄存器

但是si di均不能拆开为两个8位的寄存器来使用。                            Pause 150

29.关于div指令

   除数为8位或16位,存于一个寄存器或一个内存单元中。不能是立即数。

   被除数16位或32位,默认存在于axdx ax中(此时dx中存高16位,ax存低16位)

   结果存于  商在al16/8)余数在ah或商在ax(32/16)余数在dx

   格式为 div reg

          div 内存单元                      div byte ptr bx

30.定义数据的伪指令  db(define byte)   dw(define word)  dd(define double word)

   dup是一个操作符同上述三个一样都是被编译器识别的符号。它和上述三个配合使用用来重复定义相同类型的数据。

格式   数据类型 重复次数 dup(循环体)

   db 1000 dup(0)    dw 220 dup(0FFFFH)  db 10 dup1,2,3   db 10 dup(`abc`,`ABC`)

31.转移指令的概念:可以修改IP或可以同时修改CSIP的指令。即可以控制CPU执行                    

  某处内存中代码的指令。

8086CPU的转移行为分为:段内转移(只修改IP  jmp ax 段间转移(同时修改cs ip  jmp 1000:0         

 其中段内转移又可以分为  短转移(IP变化范围-128——127 近转移(-32768——32767

8086的转移指令有以下几类:无条件转移指令(jmp 条件转移指令 循环指令(loop) 过程 中断   以上五类转移指令虽然前提可能是不同的,但其转移原理是类似的。此章我们着重学习jmp来深入理解转移指令原理。

32Offset在汇编语言中是由编译器识别的符号,功能是获得标号的偏移地址。

    这里的标号可以指语句标号也可以是任何标号。

  mov ax,offset s

33.jmp指令 即无条件转移指令。

Jmp short 标号 (转移到标号处执行指令)此处标号为代码段中的标号。

P176 177CPU在执行jmp指令的时候并不需要转移的目的地址。

我们知道,我们编写的汇编源程序、debug中的汇编代码、机器码 这三者跟CPU的亲近程度是不同的,机器码最贴近CPU。我们通过jmp指令及其对应的机器码可知:当目的地址不同而所转移的指令相同时,机器码是一样的。这说明cpu在执行jmp指令的时候是不需要转移的目的地址的。

CPU不是神仙,它是如何转移到目的指令的呢?见P178

  jmp short 标号 这条指令的机器码,并不包含转移指令的目的地址,而是包含了IP所要转移的位移。其中这个位移是编译器根据程序中的标号计算出来的。显然这个位移是在汇编编译的时候的到的。

由此便可以得到转移指令真正的功能:jmp short s    ip=(ip)+8位位移   段内短转移

                              Jmp near ptr s    (ip)=(ip)+16位位移   段内近转移

34jmp far ptr 标号 为段间转移,又称远转移。

  Far ptr在这里也就指明了指令用标号段地址和偏移地址来修改CSIP

远转移同短转移和近转移不同之处就很明显了:因为它是段间转移所以CS也是要修改的,所以它的机器码中装的不是所要变化的位移,而是真正就是转移指令的目的地址,包括段地址和偏移地址。其中偏移在高位内存单元中,段在高单位。

35.jmp指令后面不仅可以跟代码段中的标号,可以使执行指令的入口迅速转移到标号处,还可以后跟一个寄存器,是IP的值改为16位寄存器中的值,实现段内转移。

同样,Jmp后面还可以跟内存单元,此时既可以实现段内转移也可以实现段间转移。

A   jmp word ptr ds:[bx]                   (ip)=字单元中的16位位移量

B   jmp dword ptr ds:[bx]    ip=字型内存单元中内容 CS=(内存单元地址+2

36P181的检测点9.1来看,我们可以总结:我们可以用jmp指令来控制指令的转移。无论目的指令前面有没有标号,有就好说了,

没有的话就用例题所用的方法,找到它的地址,若是段内转移直接用寄存器或字型的内存单元即可;若是段间转移就借助一个双字的内存单元。

37jcxz指令为条件转移指令,所有的条件转移指令都是短转移。所以在对应的机器码中都是要转移的位移,而不是转移指令的目的地址。且IP位移范围-128——127用补码表示。

  指令格式jcxz 标号   (如果(cx=0,则转至标号处执行指令) jmp if cx=zero

  8位位移在编译时得出,算法为 标号处指令地址sub  jcxz指令后第一个字节的地址。

如果cx的值非零,则什么操作也不做       if((cx)==0)   jmp short 标号

38.loop指令是循环指令,循环指令都是短转移。 格式:loop  s  (先做cx-- 若非零则跳转)

   小总结:cx=0跳转:jcxz      cx=!0跳转:loop

39.浅谈根据位移进行转移的意义:对于段内转移,机器码中没有转移指令的目的地址而是偏移地址,这样做有利于代码段在内存中浮动分配。

40

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值