一:前言
这篇blog记录我阅读汇编语言(王爽)的心得,每单元的检测点解答。
二:第一章:基础知识
总线bus:分为数据总线,控制总线,地址总线
地址总线的宽度决定了CPU能对多少内存单元进行寻址(寻址能力)
数据总线:决定了CPU和外界的数据传送速度
控制总线:决定了CPU对外部器件的控制能力
内存:内存是对各种芯片(显卡,网卡,随机存储器)的RAM和ROM的物理地址编址,即物理地址对虚拟地址的一一映射。这样,即使是不同的硬件,也可以进行无差别的读写。
检测点1.1
这里我又一个误区:地址总线不是对每一个bit寻址,应该是对每一个byte
第二章:寄存器
寄存器:通用寄存器,段寄存器,变址寄存器
通用寄存器:
AX accumulator 累加寄存器
BX base 基址寄存器
CX count 计数寄存器
DX data 数据寄存器
段寄存器 (8086不支持数据直接送入段寄存器)
CS:IP code segment instument pointer 指令地址
SS:SP stack segment stack pointer 栈地址
DS data segment 要访问数据的地址
ES extra segment
变址寄存器
BP base pointer
SI source index
DI destination index
监测点2.1
检测点2.3
第三章:寄存器(内存访问)
SS:SP 指向栈顶元素
push (寄存器,段寄存器,内存单元,直接数) == 先SP-2,后把数据放入SS:SP
pop (寄存器,段寄存器(除cs,ip),内存) == 先:取出数据,后:SP+2
检测点3.1
检测点3.2
第四章:第一个程序
程序模板:
; multi-segment executable file template. assume ds:data,ss:stack,cs:code data segment ; add your data here! pkey db "press any key...$" ends stack segment dw 128 dup(0) ends code segment start: ; set segment registers: mov ax, data mov ds, ax mov es, ax ; add your code here lea dx, pkey mov ah, 9 int 21h ; output string at ds:dx ; wait for any key.... mov ah, 1 int 21h mov ax, 4c00h ; exit to operating system. int 21h ends end start ; set entry point and stop the assembler.
第5章:[BX]和loop指令
寻址:需要内存地址和内存单元长度。 byte ptr word ptr dword ptr
段地址默认是ds,也可以显式ds:[ ] , cs:[ ] , ss:[ ] ,es:[ ]
[idata] | 直接寻址 |
[bx] | 寄存器间接寻址 |
[si] | |
[di] | |
[bp] | |
[bx+idata] | 寄存器相对寻址 |
[si+idata] | |
[di+idata] | |
[bp+idata] | |
[bx+si] | 基址变址寻址 |
[bx+di] | |
[bp+si] | |
[bp+di] | |
[bx+si+idata] | 相对基址变址寻址 |
[bx+di+idata] | |
[dp+si+idata] | |
[dp+di+idata] |
loop和cx配合使用 cx count计数寄存器
loop s == cx=cx-1 如果cx!=0 执行标号s
loop s: loop这条语句到标号s的偏移量
第6章:包含多个段的程序
assume ds:data,ss:stack,cs:code
数据段 data segment
;放数据 要表明数据大小 db / dw / dd
data ends
栈段 stack segment
; 要表明数据大小 通常为db 16 dup(0)
stack ends
代码段 code segment
;code
code ends
检测点6.1
第7章:
add +
sub -
mul *
乘数位8位,一个乘数默认放在AL,AX放结果 乘数为16位,一个乘数默认放在AX,结果:高位DX,低位AX
div 除数 /
除数8位,则被除数16位,默认ax ,AL放商,AH放余 除数16位,则被除数32位,默认高位DX,低位AX,AX放商,DX放余
inc 加一
dec 减一
and 与
or 或
第9章 转移指令的原理
原理:通过位移修改IP或CS的值,通过位移(而不是地址)可以浮动装配,即使程序换了存储位置,也可以正常运行
offset 标号 从程序第一条指令到这个标号的位移。
修改CS或IP的指令为转移指令:
(1)无条件转移指令
(2)条件转移指令
(3)循环指令
(4)过程
(5)中断
无条件转移指令
jmp short 标号 == ip=ip+8位位移(有符号数)
jmp near ptr (标号,16位寄存器) == ip=ip+16位位移(无符号数)
jmp far ptr 标号 == cs,ip都改(在emu8086上,指令效果与描述不同。)
jmp word ptr 内存 == ip=内存单元数据
jmp dword ptr 内存 == cs=(内存地址+2)数据 ip=(内存地址)数据
条件转移指令
jcxz if(cx==0) jmp short 标号
检测点9..2
检测点9.3
第10章 CALL和RET指令
实现高级语言的函数能力,达到模板化程序。
子程序模板:
call s
.....
......
s:将参数压入栈中
.....。
ret
call +(位移/目的地址/寄存器/内存)
call 标号 ==push ip jmp 标号
call far ptr 标号 ==push cs push ip jmp far ptr
call reg == push ip jmp reg
call word ptr 内存 ==push ip jmp reg
call dword ptr 内存 == push cs push ip jmp dword ptr
ret == pop ip 使用栈的数据进行指令转移
retf == pop ip pop cs
检测点10.1
检测点10.2
检测点10.3、
检测点10.4
检测点10.5
第11章:标志寄存器
ZF zero flag 零标志位
PF parity flag 奇偶标志位
SF sign flag 符号标志位 有符号数
CF carry flag 进位或借位 无符号数
OF overflow flag 有符号数
adc ax bx == ax=ax+bx+CF
sbb ax,bx == ax=ax-bx-CF
DF direct flag 控制si,di递增还是递减
df=0递增 cld 使df=0
df=1递减 std 使df=1
和movsb,movsw配合使用(传送数据指令)
movsb == ((es*16+(di)) = ((ds)*16+(si)) 每次di,si增量为1 或-1
movsw = word ptr ((es*16+(di)) =word ptr ((ds)*16+(si)) 每次di,si增量为2或-2
ret movsb :ret根据cx的值重复movsb
cmp ax,bx
je 等于 zf=1
jne 不等于 zf=0
jb 低于 cf=1
jnb不低于 cf=0
ja高于 cf=0且zf=0
jna不高于 cf=1或zf=1
pushf -> push flag
popf -> pop flag
检测点11.1
检测点11.2
检测点11.3
检测点11.4
第12章 内中断
中断类型码:
除法错误 0
单步执行 1
执行into指令 4
执行int指令 int n
处理中断过程:
(1)取得中断类型码
(2)标志寄存器入栈
(3)使TF=0,IF=0
(4)CS入栈
(5)IP入栈
(6)根据中断类型码修改CS,IP
iret 与int配合
iret == pop ip ,pop cs,popf
检测点12.1
第13章:int指令
编写中断程序过程
(1)将子程序传送到目的地
(2)改变中断向量表
检测点13.1
检测点13.2
第14章:端口
只能用al或ax
in al,__ 读
out __,al写
shl逻辑左移
shr逻辑右移
sal算数左移
sar算数右移
检测点14.1
检测点14.2
第15章:外中断
可屏蔽中断:cpu可以不响应的外中断
IF=0,则不响应可屏蔽中断 IF=1 响应中断 interrupt flag
不可屏蔽中断:cpu必须响应的外中断,中断码固定为2
检测点15.1