在汇编源程序中,数据不能以字母开头,故要加0识别!
debug程序开始时DS指向的是PSP的头地址,而CS=DS+10H
不能将一个数值直接送入段寄存器,要通过其它寄存器进行传送!
(N/16+1)*16 意思是总取多16个字节存放多出的字节.N+16不等价左边的式子.
它等价于(int(N/16)+1).
一般来说,当我们要暂存数据时,都应该使用栈!
(1)只有bx,si,di,bp用在[]里进行内在单元的存取.
(2)bx,si,di,bp只能以bx与si,bx与di,bp与si,bp与di四种组合出现
形像些:
si
/
bx
\
di
si
/
bp
\
di
(3)只要在[]中使用寄存器bp,而指令中没有显性地给出段地址,段地址就默认在ss中,其它的 是不是默认存放在ds中?
数据处理的分类:写入,读取,运算!
数据存在的三个地方:CPU内,内存,端口!
push只进行字操作,pop呢?
用dd定义的数的存放,如100001它的十六进制为186A1H,则它在内存的存放形式是
A1 86 01 00
刚刚好是32位,和我们的逻辑000186A1不一样(规律:倒过来).
在一个数据段里定义的数据是连续存放的,但要看清楚它们是什么类型(dd,dw,db).
db '1634'里面一个字符占一个字节,保存的是相应的ACSII码.
loop指令是先把CX寄存器的值减1然后再判断是否是0
assume cs:code
code segment
mov ax,4c00H
int 21H
start: mov ax,0
s: nop
nop
mov di,offset s ;以下四行复制s2的第一条指令给s
mov si,offset s2 ;刚刚好覆盖了s的两条nop指令
mov ax,cs:[si] ;复制过去的内容是:"向前或向后移动多少"
mov cs:[di],ax
s0: jmp short s
s1: mov ax,0
int 21H
mov ax,0
s2: jmp short s1 ;机器码EBF6;意思是"向前移动10d个字节"
nop
code ends
end start
;9D:0000 B8004C MOV AX,4C00
;9D:0003 CD21 INT 21
;9D:0005 B80000 MOV AX,0000
;9D:0008 EBF6 JMP 0000 EBF6复制过来后前移10个字节即跳到0000
;9D:000A BF0800 MOV DI,0008
;9D:000D BE2000 MOV SI,0020
;9D:0010 2E CS:
;9D:0011 8B04 MOV AX,[SI]
;9D:0013 2E CS:
;9D:0014 8905 MOV [DI],AX
;9D:0016 EBF0 JMP 0008
;9D:0018 B80000 MOV AX,0000
;9D:001B CD21 INT 21
;9D:001D B80000 MOV AX,0000
对call指令的一些理解:
call word ptr 内存单元地址
书上理解:
push IP
jmp word ptr 内存单元地址
我的理解:
(1)IP的值先变成CALL指令后的第一个字节的偏移地址,然后才被压入栈;
(2)压入后再改变IP的值,即(IP)=内存单元地址的值.
call dword ptr 内存单元地址
书上理解:
push cs
push ip
jmp dword ptr 内存单元地址
开始是将此时的CS,IP(IP应该是CALL命令后的第一个字节)压入栈,CS是先压入钱的,
然后跳到内存单元中内容所指的地址,
即CS=((内存单元地址)+2),IP=(内存单元)//其实这两个是JMP指令的理解.
对X/N=int(H/N)*65536+(rem(H/N)*65536+L)/N的理解
int(H/N)*65536求出的是高16位的值,即 16位的值0000
后面16位是低16位的值,因为后面的商不会超过16位,求出的商就是低16的值,加到0000上
而(rem(H/N)*65536+L)/N算得的余数就是本X/N的余数.
注意*65536的含义是向左移多少位,后面的补零.
先算16进制再算十进制!
int是将子程序装入内在先,然后通过代号进行调用.(静态)
而call就如动态执行这样,等到运行时才装入内存.(动态)
P246的中断例程的理解
lp:push bp ;此时栈里的情况是:bp ip cs 标志寄存器
mov bp,sp
dec cx
jcxz lpret
add [bp+2],bx ;因为bp默认的段寄存器是ss,故使用了bp,而+2就指向了ip的值.
lpret:
pop bp
iret ;由cx 来决定是循环还是向下继续执行,
编写中断例程的步聚:
(1)先将代码复制到指定的位置,注意这里要指出要复制字节的长度
(2)再把指定的代码存放位置放到向量表中,因为是通过向量表进行访问的.
(3)你可以编写你的中断例程了!记得开始与结尾标志!
在in与out指令中,只能使用ax或al来存放从端口中读入的数据或要发送到端口中的数据,访问8位端口时用AL,访问16位端口时要用AX.
shl,shr指令移位多于一位时一定要将移的位数放在cl里.
BCD码4位确定一个数,如26的BCD码为0010 0110
7.8 已知对应于中断类型码为18H的中断服务程序存放在0020H:6314H开始的内存区域中,求对应于18H类型码的中断向量存放位置和内容。
在编写程序时,为什么通常总要用STI和CLI中断指令来设置中断允许标志?8259A的中断屏蔽寄存器IMR和中断允许标志IF有什么区别?
【解答】偏移地址EA=18H×4=60H,18H中断向量在中断向量表中的入口地址为00000H+60H=00060H。中断服务程序存放在0020H:6314H开始的内存区域中,所以(00060H)=0020H,(00061H)= 6314H。
IF是8086微处理器内部标志寄存器Flags的中断允许标志位。若IF=1,则CPU可以接受中断请求;若IF=0,8086就不接受外部可屏蔽中断请求INTR引线上的请求信号。在编写程序时,用STI指令使中断允许标志位IF=1,目的是使CPU能够接受中断请求,或实现中断嵌套。而用CLI指令使中断允许标志位IF=0,则可以关中断,使CPU拒绝接受外部中断请求信号。
如果8259A的中断屏蔽寄存器IMR中的某位为1,就把这一位对应的中断请求输入信号IR屏蔽掉,无法被8259A处理,也无法向8086处理器产生INTR请求。
注意:在后面加有":"的地址标号,只能在代码段中使用,不能在其他段中使用.
$表示的是本行地址,
$$则表示开始汇编的地址.
2.3总结:
执行mov指令不改变CS寄存器
执行jmp 段地址:偏移地址 改变CS和IP
执行jmp 寄存器 只改变IP不改变CS
实验五总结:
还没加载程序前:
CS:IP指向程序段的第一条指令,故CS可以知道.
SS=CS-2
DS=SS-10H ;这个知道有没有用?
加载后:
SS=CS-1;
DS=CS-2;