重点知识
1)大小写字母转换
大小写字母转换利用它们的 ASCII 码相差 20H。
注意:大写字母“A”的ASCII码值为41H(01000001B),D5=0.而小写字母“a”的ASCII码值为61H(01100001B)D5=1.和数据00100000B相异或则改变字母大小写。
2)“与”F=A•B ;“或”F=A+B;“异或”异1同0;& | ~ 异^
3)单精度浮点数:
真值=(-1)^S*(1+0.尾数)*2^(阶码-127) D31 D30-D23(8) D22-D0(23)
双精度浮点数:
真值=(-1)^S*(1+0.尾数)*2^(阶码-1023)D63 D62-D52(11) D51-D0(52)
Float 0=0000 0000H
实数转浮点:
A :100.25=0110 0100.01=1.10010001*2^6 6+127=133=1000 0101
0 -1000 0101 -1001 1000 1000 0000 0000 000
B:-1.1 = BF8CCCCC(不考虑舍入)/BF8CCCCD(考虑就近舍入)多取后4位小数,大于1000则入。
- 就近舍入!(向偶舍入),是将数字向上或向下舍入,使得结果的最低有效数字是偶数,四舍五入;
向零舍入(截断舍入)则是向靠近零的值舍入,正负数均截尾
向上舍入则是向比它大的方向靠近,负数截尾
向下舍入则是向比它小的方向靠近,正数截尾
5)为什么浮点数编码有舍入问题,整数无?
浮点数编码存在舍入问题的原因是由于浮点数的表示方式。浮点数使用有限的位数来表示实数,而实数是无限的,所以在进行浮点数编码时必然存在近似。而整数编码则是直接使用二进制来表示整数,没有精度限制和运算误差的问题,故可以精确表示。
6)常用的BCD码为8421BCD码,其中8表示D3位的权重。✔️
解释:8421 BCD码,其中8 4 2 1 分别为D3 D2 D1 D0位的权重。
7)零位扩展对应无符号数,MOVZX,符号扩展对应有符号数,MOVSX,他们使数据位数加长,但数据大小并没有发生改变。
8)321的8421码(BCD码)就是
3 2 1
0011 0010 0001
9)IA-32处理器小端存储:高对高,低对低
10)一个32位整数编码在IA-32处理器的主存中占用4个字节空间。给定起始地址为405000H,那么最高字节存放的地址:
起始地址 + 4个字节 - 1 = 405003H
- 有无符号数的截断:
当16位整数转换为8位,需要位数的低位不变,多出的高位截断。
增加位数的有符号数和无符号数的转换:首先,进行零位扩展或符号扩展,然后,进行数据位数相同的转换
- 无符号整数加法的进位:得到的值=和值被截断第N+1位/即真实和值减去2N;
有符号整数加法的溢出:(补码和值)=真实和值被截断第N+1位的结果。负溢出,相当于真实和值加上2N;正溢出,相当于真实和值减去2N.
无符号数相加有进位,低位结果正确,进位等于2N;有符号数相加有溢出,低位结果错误。
两个正数相加,结果是负数;或者两个负数相加,结果是正数;产生溢出。正溢出:最高位无进位、次高位有进位;负溢出:最高位有进位、次高位无进位
- 在同一个表达式同时存在有符号和无符号数时,有符号数隐式转换为无符号数参与运算,包括比较运算符;使用补码进行加减运算
参与运算的类型不同,会自动转换成相同类型再运算。转换的方向为向数据长度增长的方向,char->short->int->unsigned int ->long;所有float都会先转成double进行运算,哪怕只有一个float;赋值运算时,赋值号右边的类型向左边的类型转换。在表达式中,如果char和short类型的值进行运算,无论char和short有无符号,结果都会自动转换成int。如果char或short与int类型进行计算,结果和int类型相同。即:如果int是有符号,结果就是带符号的,如果int是无符号的,结果就是无符号的。
14)逻辑地址=段基地址∶偏移地址
段基地址=在主存中的起始地址;偏移地址=距离段基地址的位移量
15)代码段——段基地址:代码段寄存器CS指示;偏移地址:指令指针寄存器EIP保存
数据段——段基地址:数据段寄存器DS指示;也可以附加段寄存器ES,FS,GS指示;偏移地址:各种存储器寻址方式计算出来
堆栈段——段基地址:堆栈段寄存器SS指示;偏移地址:堆栈指针寄存器ESP保存
16)逻辑地址包含“段基地址:偏移地址”,实地址存储模型都用16位数表示,范围是0000H——FFFFH。根据实地址存储模型,只要将逻辑地址中的段基地址左移4位(十六进制1位),加上偏移地址就得到20位物理地址。例逻辑地址“1460H:0100H”表示物理地址14700H,其中段基地址1460H表示该段起始于物理地址14600H,偏移地址为 0100H。
17)类型名 PTR 变量名ptr 将变量名按照指定的类型使用
TYPE 变量名type 返回该变量所占字节数
LENGTHOF 变量名lengthof 返回整个变量的数据项数
SIZEOF 变量名 sizeof 返回整个变量占用的字节数
“?”表示初值不确定,即未赋初值
“ORG ”控制存放的偏移地址||org 100h从偏移地址100H处安排
[ ] 括起的表达式作为存储器地址指针
$ 返回当前偏移地址
复制操作符DUP重复次数 DUP(重复参数)
OFFSET 变量名 返回变量名所在段的偏移地址
SEG 变量名 返回段基地址(实地址存储模型
- 数据寻址是通过地址查找数据(操作数)
立即数寻址:数据与指令操作码一起,用常量表达
例如:MOV EAX,33221100H
机器代码:B8 00 11 22 33
操作码:B8 立即数:33221100
寄存器寻址:数据在寄存器中,用寄存器名表示,前后都可以是寄存器,但二者必须等长
例如:MOV EBX,EAX
存储器寻址:数据在主存中,用存储器地址代表;前后不能同为存储器寻址。指令编码中表达形式地址,由形式地址结合规则经过计算得到有效地址EA,处理器将有效地址转换为物理地址访问存储单元。
32位有效地址= 基址寄存器+(变址寄存器×比例)+位移量
基址寄存器:任何8个32位通用寄存器之一;变址寄存器:除ESP之外的任何32位通用寄存器之一;比例:1,2,4或8;位移量:8或32位有符号值
16位有效地址= 基址寄存器+变址寄存器+位移量
基址寄存器:BX或BP;变址寄存器:SI或DI;位移量:8或16位有符号值
存储器直接寻址:有效地址只有位移量,直接包含在指令代码中
例如:MOV AX,[2000H]
寄存器间接寻址:有效地址存放在寄存器中,寄存器内容=有效地址=偏移地址 例如:MOV AX,[BX]
寄存器相对寻址:有效地址是寄存器内容与位移量之和(地址的加减是以字节为单位)mov esi,[ebx+4] ;位移量:4
或者:mov edx ,vard[ebx] vard32位
基址变址寻址:mov edi,[ebx+esi ];功能:EDI=DS:[EBX+ESI]
相对基址变址寻址:mov eax,[ebx+edx+80h] ;功能:EAX=DS:[EBX+EDX+80H]
mov eax,[ebx*4] ;带比例的变址寻址
mov eax,[esi*2+80h] ;带比例的相对变址寻址
mov eax,[ebx+esi*4] ;带比例的基址变址寻址
mov eax,[ebx+esi*8-80h];带比例的相对基址变址寻址
19)在双操作数的指令中,目的操作数写在,前,还用来存放指令操作的结果;对应地,,后的操作数就称为源操作数
20)交换指令XCHG:xchg esi,edi寄存器与通用寄存器之间;通用寄存器或存储器间
空操作指令NOP
堆栈指令(先进后出):
Push(进站):先将ESP减小作为当前栈顶,后将源操作数传送到当前栈顶;sub esp,4; mov[esp],eax;
POP出战:先将栈顶数据传送到目的操作数,后ESP增加作为当前栈顶;mov eax,[esp]; add esp,4;
地址传送指令:LEA
lea eax,[ad]就是将表达式ad值放入eax寄存器,示例如下:
lea eax,[401000h]; 将值401000h写入eax寄存器中
lea eax,c;其中c为一个int型的变量,该条语句的意思是把c的地址赋值给eax;
lea指令右边的操作数表示一个精指针,上述指令和mov eax,401000h是等价的,不需类型一致
带进位的加法指令ADC:两个操作数相加,再加CF,结果送目的操作数;ADC reg,imm/reg/mem ;reg←reg+imm/reg/mem+CF
用于与ADD指令相结合实现多精度数的加法:
先将两个操作数的低32位相加(用ADD指令)
再加高位部分、并将进位加到高位(用ADC指令)
带借位的减法指令SBB:目的操作数减去源操作数,再减CF,结果送目的操作数;SBB reg,imm ;reg←reg-imm-CF
用于与SUB指令相结合实现多精度数的减法
先将两个操作数的低32位相减(用SUB指令)
然后减高位部分、并减去借位(用SBB指令)
增量指令INC:只有一个操作数:寄存器或存储单元;对操作数加1(增量)再将结果返回原处INC reg/mem。不影响进位CF标志,影响其他状态标志位
减量指令DEC:只有一个操作数:寄存器或存储单元;对操作数减1(减量)再将结果返回原处;DEC reg/mem不影响进位CF标志
求补指令NEG:对操作数执行求补运算,即用零减去操作数NEG reg/mem
无符号数乘法MUL ;有符号数乘法IMUL ;DIV IDIV
32 位模式下,MUL指令有三种类型:不能是立即数!!!
执行 8 位操作数与 AL 寄存器的乘法;——AX
执行 16 位操作数与 AX 寄存器的乘法;——DX:AX
执行 32 位操作数与 EAX 寄存器的乘法。——EDX:EAX
MUL 指令中的单操作数是乘数。如果乘积的高半部分不为零,则 MUL 会把进位标志位和溢出标志位置 1
16位数除以8位数:
格式:div 除数,比如div cl。
除数:由8位的通用寄存器或者内存单元来提供,不能是立即数。
被除数:放在ax中。
结果:商存放在al中,余数存放在ah中。
32位数除以16位数:
格式:div 除数,比如div cx。
除数:由16位的通用寄存器或者内存单元来提供,不能是立即数。
被除数:低16位放在ax中,高16位放在dx中。
结果:商存放在ax中,余数存放在dx中。
操作数:如果乘积的高半部分不是其低半部分的符号扩展,则进位标志位和溢出标志位置 1
双操作数:会按照目的操作数的大小来截取乘积,乘积的高半部分会被丢弃。如果被丢弃的是有效位,则溢出标志位和进位标志位置 1。零位扩展 MOVZX r16,r8/m8;符号扩展 MOVSX r16,r8/m8
ADD OR XOR设置CF=OF=0影响SF,ZF和PF
NOT不影响标志位
逻辑左移指令 SHL逻辑右移指令 SHR
算术左移指令 SAL算术右移指令 SAR
ROL 各位同时左移,最高位循环进入最低位和CF(字节?)
当多字节整数以四位为单位进行循环移位时,其效果相当于一次向右或向左移动一个十六进制位。ROR 各位同时右移,最低位进入最高位和CF
RCL CF作为附加位,各位同时左移,CF进入最低位
RCR CF作为附加位,各位同时右移最低位进入CF
CMP(比较)指令,执行从目的操作数中减去源操作数的隐含减法操作
21)进位标志CF溢出标志OF(cf只有正溢出)
运算结果为0,则ZF=1,否则ZF=0
运算结果最高位为1,则SF=1;否则SF=0
当运算结果最低字节中“1”的个数为零或偶数时,PF=1
22)
段内转移,相对寻址JMP label //IP ← IP + 位移量
段内转移,间接寻址JMP r16/m16 //IP ← r16/m16
即将一个16位寄存器或主存单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容。例如:
JMP AX //IP ← AX; JMP WORD PTR[2000H] //IP ← [2000H]
段间转移,直接寻址:将标号所在段的段地址作为新的CS值,标号在该段内的偏移地址作为新的IP值。
JMP FAR PTR label //IP ← label的偏移地址,CS ← label的段地址
段间转移,间接寻址:用一个双字存储单元表示要跳转的目标地址。
JMP FAR PTR mem //IP ← [mem],CS ← [mem + 2]
段间间接转移指令这个目标地址存放在主存中连续的两个字单元中,其中低位字送IP寄存器,高位字送CS寄存器。例如:
MOV WORD PTR[BX], 0
MOV WORD PTR[BX + 2], 1500H
JMP FAR PTR[BX] //转移到1500H : 0
23)条件转移指令中的条件如下表所示:
无符号数用高(Above)、低(Below)
低于(不高于等于):JB(JNAE);不低于(高于等于):JNB(JAE)
低于等于(不高于):JBE(JNA);低于等于(高于):JNBE(JA)
有符号数用大(Greater)、小(Less)
小于(不大于等于):JL(JNGE);不小于(大于等于):JNL(JGE)
小于等于(不大于):JLE(JNG);不小于等于(大于):JNLE(JG)
比较指令CMP:按减法影响状态标志
测试指令TEST:按逻辑与影响状态标志
条件转移指令不影响标志,但要利用标志
JZ/JE ZF=1 ;JNZ/JNE ZF=0
JS SF=1 ; JNS SF=0
JP/JPE PF=1 ; JNP/JPO PF=0
JO OF=1 ; JNO OF=0
JC CF=1 ;JNC CF=0
24)neg eax
;条件不满足:EAX<0,为负数
;需求补得正值
LEAVE指令相当于如下两条指令的功能
mov esp,ebp
pop ebp
LOOP label
;ECX←ECX-1;若ECX≠0,循环到LABEL
;否则,顺序执行
JCXZ指令在CX寄存器为0时退出循环;LOOP指令首先将计数值CX减一,然后判断计数值CX是否为0。CX不为0则继续执行循环体内的指令;CX为0表示循环结束。LOOPZ和LOOPNZ指令中要求同时ZF为1或0才进行循环,用于判断结果是否为0或相等,以便提前结束循环
JECXZ label
;ECX=0,转移;否则顺序执行
25)dispmsg dispc(AL) dispsid disphd dispcrlf(换行)disprd(显示32位寄存器数值)readmsg readc readhd readsid readuid
DISPMSG 显示字符串(以0结尾)
DISPC 显示一个字符
DISPCRLF 光标回车换行,到下一行首个位置
DISPRD 显示8个32位通用寄存器内容
DISPRF 显示6个状态标志的状态
DISPHD 以十六进制形式显示8位数据
DISPUID 显示无符号十进制整数
DISPSID 显示有符号十进制整数
- 标志位 当实际的减法发生时,CMP指令按照计算结果修改溢出、符号、零、进位、辅助进位和奇偶标志位。当执行到CMP指令的时候会读取这两个寄存器的内容,并加以减法运算,结果本身不保留,并按照结果设置符号位(属算术运算)。如果比较的是两个无符号数,则零标志位和进位标志位表示的两个操作数之间的关系如下表所示:
CMP结果 ZF CF
目的操作数 < 源操作数 0 1
目的操作数 > 源操作数 0 0
目的操作数 = 源操作数 1 0
如果比较的是两个有符号数,则符号标志位、零标志位和溢出标志位表示的两个操作数之间的关系如下表所示:
CMP结果 标志位
目的操作数 < 源操作数 SF ≠ OF
目的操作数 > 源操作数 SF = OF
目的操作数 = 源操作数 ZF = 1
若SF=0,OF=0 则说明了此时的值为正数,没有溢出,可以直观的看出,oprd1>oprd2;
若SF=1,OF=0 则说明了此时的值为负数,没有溢出,则为oprd1<oprd2;
若SF=0,OF=1 则说明了此时的值为正数,有溢出,可以看出oprd1<oprd2;
若SF=1,OF=1则说明了此时的值为负数,有溢出,可以看出oprd1>oprd2;
27)MOV指令使用规则:
(1) 目标操作数无立即方式 例如,MOV 03H,AL; 为错误指令
(2)数据传送应注意数据类型的一致(要求等字长) ;或是至少有一个是确定的,另一个依附这个。
例如,MOV AL,1000H; 指令有类型错误
MOV AX,BL;指令有类型错误
MOV [BX], 9;是错误指令
(3) 两个操作数不能同时为存储器操作数 例如,MOV [2000H], [BX]; 是 错误指令
(4) 段寄存器不能用立即数赋值 例如,MOV DS,1000H; 错误指令可以: MOV AX, 1000H; MOV DS,AX ; 赋初值
(5)不能改变CS的值 例如, MOV CS,AX;是错误指令
(6)两个操作数不能同时为段寄存器 例如,MOV ES,DS; 错误指令 可以通过AX
(7)立即数到存储单元的数据传送 例如, MOV [BX], 9;是错误 指令
应该写为: MOV BYTE PTR [BX] ,9 或 MOV WORD PTR [BX], 9
28)在汇编里面使用数组的话,是使用地址来实现的,即使用数组首地址和偏移量。
取数组:lea ebx,nbrArray lea 目的地址,源数据
目的地址通常是一个32位的寄存器,源数据是储存器的值
偏移量:add ebx,4 通过add进行实现,让带着数组首地址的ebx寄存器加上4个字节的byte储存空间,则,此时的ebx指向的是数组的下一个位置
修改值:mov [ebx],4注意和上面的差别,上面的是ebx直接加上4,代表的是地址,而[ebx]则是对ebx里储存的地址的值加上4(寄存器间接取值,可以和c++的*进行比较)