汇编注意点
1.在进行数据传送或运算时,要注意指令的两个操作对象的位数应当是一致的,
如 mov ax, bl
mov al, 100h
会提示错误:Operand types out of range
Value out of range
2.内存并没有分段,段的划分来自于CPU,段的起始地址必须是16的倍数.
3.CS,IP指明了CPU当前要读取指令的地址,CS为代码段寄存器,IP为指令指针寄存器,过程为从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器,IP指向下一条指令,执行指令。清楚是IP先指向下一条指令,再执行指令。CPU只认被CP:IP指向的内存单元的内容为指令
4.8086CPU不支持将数据直接送入段寄存器的操作,这属于硬件设计的问题
5.任意时刻,SS:SP指向栈顶元素,,而且是从高向底存
入栈时,SP先改变,再入栈,出栈时,先出栈,再改变sp,两者刚好相反8086CPU入栈出栈都以字为单位进行
6.CPU不保证我们对栈的操作不会超界,换句话说,CPU只知道栈顶在哪里,而不知道我们安排的栈空间有多大,
7.push,pop等栈操作指令,修改的只是SP,也就是栈顶的变化范围最大为0-FFFFH
8.cx-loop,loop时,要先将cx=cx-1,再对cx判断。
9.直接用masm写mov al, [1]之类的,编译器会把它认为是mov al, 1,所以要么用一个寄存器作中间量,
mov bx,1
mov al,[bx]
要么直接给出前缀:mov al, ds:[0]
10.只有bx,bp,si,di这四个寄存器可用于内存单元的寻址,而且bx,bp不能组合,si,di不能组合,
也就是不能写成
mov ax,[bx+bp]
mov ax,[si+di]
11.在没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度,X在汇编指令中可以为word或byte
如:mov word ptr ds:[0],1
inc word ptr [bx]
add word ptr[bx],2
而push [100h]是不用指明的,因为push指令只进行字操作
12.jmp short 标号的功能为IP=IP+(标号处地址-jmp指令后第一个字节的地址),范围为-127-128,补码表示
jmp near ptr标号为IP=IP+16位位移,范围为-32768-32767用补码表示
13.jcxz相当于if(cx==0) jmp short 标号
14.ret相当于pop IP,retf相当于pop IP pop CS
15call相当于
push IP(这个IP指向了call后一条指令,因为先变IP,再执行指令)
jmp near ptr 标号
call far ptr 标号 相当于
push cs
push IP(这个IP指向了call后一条指令,因为先变IP,再执行指令)
jmp far ptr 标号
16.ret n表示
ret
add sp n
用于平衡堆栈
17.code segment
那么code保存的值是段地址,比如assume cs:code
那么mov ax, code和mov ax, cs是一个意思。
18.只要在[...]中使用寄存器bp,并且没有显示给出段地址,段地址就默认在ss中.
19.1、关于 mov ax,offset str 和 lea ax,str之间的区别
他们之间的最大区别在于Offset str是一条伪指令,与SEG DATA之类相似,它在编译和连接过程被赋给一个值,你可以把它看成一个立即数,
如 MOV BX,OFFSET str ;源代码
如果str的地址是2010,则编译后该行变为:
MOV BX,2010 ;执行代码
而lea ax,str是把str的内存指针赋给ax,你可以把它看成内存变量。他是在运行期间计算获得的。(所以总体说来,Offset是一种静态的方式,而Lea是动态方式)另外,MOV ax,offset str是一条2字节立即寻址指令,lea ax,str是一条3字节内存寻址指令,后者虽然有比较灵活的寻址方式,但前者具有更小的容量和更快的执行速度,推荐尽可能使用MOV ax,offst str。当然,offsset后面只能是标号或变量名
20.lea ecx,[eax+0x30]就等于
mov ecx, 0x30
add ecx, eax
从指令长度和执行速度来看.lea ecx,[eax+0x30]要好.
因为不支持mov ecx, eax+0x30这样的命令!