1.=======================================================================
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
DW 16 DUP (0)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,STACKS
MOV SS,AX
MOV SP,32;这边自己设置一个堆栈
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;此处输入代码段代码
MOV AX,0
PUSH AX ;将AX放入堆栈中
POPF ;将堆栈中的栈顶的值取出来,让后放入到标志寄存器中
MOV AX,0FFF0H
ADD AX,0010H
PUSHF ;将标志寄存器中的值放入到对战中
POP AX ;将堆栈中的值再取出来给AX
AND AL,11000101B
AND AH,00001000B ;对AX进行与操作
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;这边是测试代码
;直接将寄存器中的值拿出来放到AX中,看是什么样的结果,代码是
;
;PUSHF
;POP AX
;
;这边,我们直接在DEBUG中进行测试,这边测试后,AX=3202H
;这是标志寄存器中的值,也就是二进制的 0011 0010 0000 0010
;也就是说标志寄存器中的1,3,5,8中的值原来默认的是1,0,0,0,这是
;为什么呢,这边我就真的是不知道了。而原来寄存器中IF的默认值是
;1,也就是响应CPU外部的可屏蔽中断发出的中断请求,这是可以理解的
;但是为什么1,5位置的默认值是1,这边我真的是不清楚了,不知道哪里
;有资料详细的讲明这些东西。TF是单步中断请求标志,如果是按照上面
;的这种解释的话,我们在重新的来看一下我们的原来的代码,这边我们
;进行一个加法运算,因为进行加法运算后,标志寄存器的值的符号表示
;是 NV UP DI PL ZR NA PE CY,对应的值是0 0 0 0 1 0 1 1,如果是这
;样的话,我们现在默认,运行加法运算后,其他默认的没有标志位的寄存
;器的值是没有改变的,也就是在1,3,5,8中的值还是原来的1,0,0,0,这样
;我们得到的AX的值就是0011 0000 0100 0111,既是AX=3047H,但是,
;并不是我们想要的3047H,这是为什么呢?很明显的,我们的假设是
;错误的,但是,为什么运行加法后,标志寄存器中的1,3,5,12,13,14,15
;位置的位也相应的产生了变化呢,现在我们是确定有变化了,但是这是
;为什么了,书中对这些空置的标志位没有理会,但是,为什么程序
;运行的时候,还要这样子对空置标志位进行运算呢,这真的是匪夷所思
;了。或者是另外的一中可能,我对原来的代码理解的不是很透彻,还是
;CPU本身运行机制的问题呢。
;;;;;;;;;;;;;;
;这边从新进行测试,想一下,标志寄存器是放在内存中吗,应该不是的,
;按理说应该是和通用寄存器一样,但是他们是放在那里呢,这个真的是不明白,
;网上找找看吧,是单独的存放到一个位置吗,是在哪里呢?
;寄存器是CPU的内部元件,应该说和内存是独立开来的,这点要明白,而对于
;外部寄存器,它是同时具有内寄存器和内存储器的特点。不能看清寄存器,
;特别是标志寄存器的变化过程和变化的机制,但是很想知道,现在终于是找到
;答案了,原来是我自己理解错了,就是那么简单的高位,低位的问题了,但是
;自己就是没有缓过来,呵呵,但是现在还是由一个问题了,为什么标志位的
;第一位的默认值是1呢,这真的是头大!接下来代码也就简单了,看来是不能随便
;的错过什么问题啊,不然是会后悔的,糟糕的
MOV AH,4CH
INT 21H
CODES ENDS
END START
;这边执行行到POP AX后,AX 的值是3047H,这是为什么呢,我真的是
;不明白了,这些标志寄存器的结构真的是不大了解了。所以这边为了
;了解标志寄存器的结构,我这边必须进行一些测试。
2.=======================================================================
DATAS SEGMENT
DB 16 DUP (0)
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV ES,AX
MOV AX,0F000H
MOV DS,AX
;MOV SI,0FFFFH
;MOV DI,15
;MOV CX,16
;这边我们使用MOVSW进行字符串的传送
MOV SI,0FFFEH
MOV DI,14
MOV CX,8
STD
;REP MOVSB
REP MOVSW
MOV AH,4CH
INT 21H
CODES ENDS
END START
;这边如果我用的是字传送的时候就不可以了呢,我有修改cx为8,
;但是,为什么这样是不可以的呢,这个肯定是要搞明白的,这边
;我们还是要一个一个的进行简单的测试的。也就是从MOVSW开始进行
;测试,然后再找出其中的蹊跷。先看下书怎么说MOVSW的。
;很兴奋的,这边终于是发现问题了,因为你要知道,这边的SI,DI是相对应的
;指向字符串的最后一个字节或者是最后的一个字,如果你使用MOVSB,
;那么,SI对应的就是指向字符串的最后的一个字节,但是如果使用的是
;MOVSW的话,那么SI对应的就是指向字符串的最后一个字的首地址了,
;而这边的字的首地址应该是如上面代码中表示,对应的DI也是同样的原理的
;而刚才我没有改过来,SI还是指向字符串的最后的一个字节,但是
;我使用的是MOVSW的时候,在程序运行的时候,他们要找到对应的是字
;但是对于每一个字(有两个字节组成)的首地址应该是偶数型地址(系统
;默认的吧,这个我真的是也不太清楚了,反正就是这样子了,这是硬件
;方面的问题吧),所以在运行的时候就出现了问题了。总的来说
;MOVSB 和 MOVSW使用的方法是类似的,只是如果字符串是奇数长度的
;时候,我们正常使用的是MOVSB,如果是偶数长度的时候,我们就
;尽量的时候MOVSW,因为这样子,速度应该是更快的。
3.==========================================================================
这边事BIOS中断例程INT10 的2号中断和9号中断的例子和巩固: