(进度:已完结)
前注
王爽汇编语言知识点整理,欢迎观看。
正文
-
一个字由两个字节组成,这两个字节分别称为高位字节和低位字节,一个字节由8个bit组成(也就是两个内存单元),可以存在8位寄存器中,8086cpu都是16位
-
CPU访问内存时由段寄存器提供段地址,8086CPU的四个段寄存器是:CS、DS、SS、ES
-
SS:SP始终指向栈顶;CS:IP指向执行的下一条代码;DS存储默认段地址;CX用来记录循环次数
-
载入程序时,CS保存了程序的长度(也是程序返回时的偏移地址),IP为0000h
-
用Debug的R命令查看、改变CPU寄存器的内容:
用Debug的D命令查看内存中的内容;
用Debug的E命令改写内存中的内容;
用Debug的U命令将内存中的机器指令翻译成汇编指令;
用Debug的T命令执行一条机器指令;
用Debug的A命令以汇编指令的格式在内存中写入一条机器指令。
用Debug的G命令执行指令到所指定的IP地址停止。
用Debug的P命令快速执行LOOP循环到结束。 -
常用符号ASCII码值
: 58
[ 91
] 93 -
PSP占用10H即256字节,虽然和程序区物理地址相连,但是段地址不同
-
使用p命令执行int 21
-
汇编源程序中,数据不能以字母开头,需要在前面加0
-
debug和编译器masm对于[data]有不同解释,debug将其作为一个内存单元,masm将其作为data处理。可以在masm中使用类似于ds:[data]显式地指定内存单元
-
mov指令当在寄存器之间时,占两个字节;当在寄存器和立即数之间时,占三个字节(其余指令不建议记,-u查看更好,太多了)
-
要知道assume是伪指令,是由编译器执行的,也是仅在源程序中存在的信息,CPU并不知道它们。我们不必深究assume的作用,只要知道需要用它将你定义的具有一定用途的段和相关的寄存器联系起来就可以了。
-
[bx+idata]一次移动两个字节
-
si和di是8086中和bx功能相近的寄存器
-
只有bx、si、di和bp四个寄存器可以用于内存单元寻址
-
bx、si、di和bp这四个寄存器可以单独出现,或者只能以四种组合出现:bx和si、bx和di、bp和si、bp和di
-
只要在[…]中使用寄存器bp,而指令中没有显性地给出段地址,段地址就默认在ss中。
-
用操作符Xptr指明内存单元的长度,X在汇编指令中可以为word或byte
-
push指令只进行字操作
-
div指令——除数:有8位和16位两种,在一个reg或内存单元中。被除数:默认放在AX或DX和AX中,如果除数为8位,被除数则为16位,默认在AX中存放(结果在al存放,余数在ah存放);如果除数为16位,被除数则为32位,在DX和AX中存放,DX存放高16位,AX存放低16位(结果在ax存放,余数在dx存放)。
-
dup 用来进行数据的重复
-
offset功能是取得标号的偏移地址(CSAPP讲过这个欸)
-
jmp word ptr 内存单元地址(段内转移)
-
jmp dword ptr 内存单元地址(段间转移)(CS)=(内存单元地址+2)(IP)=(内存单元地址)
-
我们从jcxz的功能中可以看出,“jcxz标号”的功能相当于:if((cx)==0)jmp short标号;
-
nop 空操作指令
-
ret指令用栈中的数据,修改IP的内容,从而实现近转移;retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移(第一个pop的是IP)。
-
call+ret=子程序
-
mul指令:8位一个默认放在AL中,另一个放在reg或者内存字节单元中;16位一个默认放在AX中,另一个放在16位reg或者内存字单元中;结果8位在AX中,16位高位在DX中,低位在AX中
-
flag寄存器(使用蓝色标出)
-
ZF标志位如果指令执行之后结果为0那么zf=1反之zf=0;
-
PF标志位,它记录相关指令执行后,其结果中所有bit位的个数是否为偶数,偶数为1奇数为0;
-
SF标志位,记录指令执行以后,结果是否为负(默认进行的运算是有符号运算),负数为1,非负为0
-
CF标志位记录无符号运算结果的进位值/借位值
-
OF标志位记录有符号运算结果是否溢出
-
传送指令、inc指令、loop指令不影响标志位
-
or指令和and指令等逻辑操作对标志寄存器的影响是:OF和CF位被清零,SF、ZF、PF位的状态依计算结果而定,AF位的状态未定义。
-
adc带进位加法指令 sbb带借位减法指令 cmp比较指令
-
因为溢出导致了实际结果为负(sf值为正),那么真正的结果必然为正,反之亦然
-
movsb的功能是将ds:si指向的内存单元中的字节送入es:di中,然后根据标志寄存器df位的值,将si和di递增或递减。df=0增加,df=1减少。(传送的原始位置:ds:si;传送的目的位置:es:di;传送的长度:cx;传送的方向:df。)
-
movsw的功能是将ds:si指向的内存字单元中的字送入es:di中,然后根据标志寄存器df位的值,将si和di递增2或递减2。df=0增加,df=1减少。
-
上面两个指令常配合rep使用,rep表示根据cx的值重复当前命令。
-
pushf将标志寄存器的值压栈,popf从栈中弹出数据送入标志寄存器
-
中断向量表中一个表项存放一个中断向量,一个表项占用两个字。高地址存放段地址,低地址存放偏移地址。
-
可以使用offset a-offset b的方法计算代码段的长度
-
存储N号中断源对应的中断处理程序入口的偏移地址的内存单元的地址为:N*4
-
存储N号中断源对应的中断处理程序入口的段地址的内存单元的地址为:N*4+2
-
TF=1,执行单步中断程序
-
CPU可以直接读写以下3个地方的数据。
(1)CPU内部的寄存器;
(2)内存单元;
(3)端口。 -
mov ax,ds:[8];
假设执行前(ds)=0
执行时与总线相关的操作如下所示:
①CPU通过地址线将地址信息8发出;
②CPU通过控制线发出内存读命令,选中存储器芯片,并通知它,将要从中读取数据:
③存储器将8号单元中的数据通过数据线送入CPU。 -
in al,60h;
从60h号端口读入一个字节执行时与总线相关的操作如下:
①CPU通过地址线将地址信息60h发出;
②CPU通过控制线发出端口读命令,选中端口所在的芯片,并通知它,将要从中读取数据;
③端口所在的芯片将60h端口中的数据通过数据线送入CPU。 -
访问8位端口用al,访问16位端口用ax
-
端口写入out,端口读出in
-
shl是逻辑左移指令,它的功能为:
(1)将一个寄存器或内存单元中的数据向左移位;
(2)将最后移出的一位写入CF中;
(3)最低位用0补充。 -
shr是逻辑右移指令,它和shl所进行的操作刚好相反。
(1)将一个寄存器或内存单元中的数据向右移位;
(2)将最后移出的一位写入CF中;
(3)最高位用0补充。 -
cli 禁止中断发生
sti 允许中断发生 -
按下一个键时产生的扫描码称为通码,松开一个键产生的扫描码称为断码。断码=通码+80h。
-
键盘缓冲区高字节存放扫描码,低字节存放ASCII码
-
int 16h从键盘缓冲区读取一个键盘输入,并将其从缓冲区中删除
-
组合类型
与其它模块中的同名段在满足定位类型的前提
下具有的组合方式:
NONE: 不组合
PUBLIC: 依次连接(顺序由LINK程序确定)
COMMON: 覆盖连接
STACK: 堆栈段的依次连接
AT 表达式:段定义在表达式值为段基的节边界
MEMORY: 相应段在同名段的最高地址处。 -
宏: 源程序中由汇编程序识别的具有独立功能的一段程序代码
-
1 宏命令伪指令由宏汇编程序处理,过程由CPU处理
2 宏指令:简化源程序,不能简化目标程序
子程序:产生相应的机器代码,每次调用用call,不重复出现机器代码,节省内存
3 执行时间
总结:
我用了大概一个月学完本书,如果将全部精力放在上面的话,大概2~3星期就可以学完。
毫无疑问,这是一本理论实践俱全的书籍,在DosBox上敲指令也是比较愉快的学习经历。对于在学校要接触到8086汇编的童鞋来说,我非常推荐这本书。
剩下的部分等我学完x86再来总结吧。