//不知不觉2017了,看着博客发布日期是2016-07-15.
相关文档
汇编指令基础
DIV
div有毒,除数是8位,被除数就得是16位。被除数是16位,除数就得是32位。
div word/byte ptr [ax]
8位情况下,al存商,ah存余数。16位情况下ax存商,dx,存余数。
dw,db,dd
等于开辟内存,dw是开辟4位,称呼为1字。db是2位,称呼为1字节。dd为8位,顾名思义,双字。
db 1 = 01 , dw 1 = 0001 , dd 1 = 00000001
各个寄存器作用
- cs,都名思意,Codesegment
- ds,也是很容易理解,数据段寄存器
- ss,栈寄存器
- 通用寄存器有好多,ax,bx,cx,dx,si,di,其中,ax,bx,cx,dx可以分为两个8位寄存器位[]h(igh)高位和[]l(ow),储存八位数据
- bp,和ss联用,BP为基址指针,作为校准使用,一般用途是[sp+bp]( 其实是存取某时刻的栈顶指针,以方便对栈的操作,如获取函数参数、局部变量等。
- ip,和cs联用,指向下一步执行代码段的地址
- sp,和ss联用,一直指向栈顶的指针,pop为sp+=2,push为sp-=2,ss为空时sp指向0,如果push或者pop过多会溢出或者越位,危险!
- ES,附加段寄存器,和di寄存器相关联使用,一般是es:di
寻址方式
debug下可以直接[idata],但是在MASM下会忽略[],直接传送数字去了,而不是指向地址的值,[ 0 ]除外。想要那样寻址,一般可以使用 ds : [偏移地址]
jmp
- jmp short 标号 : 段内短转移,对IP的范围为(-128~127)
,并不是通过段:偏移地址来跳转,而是计算目前这条语句到跳转语句的偏移地址来跳转,所以说CPU并不会知道要跳转的地址,而是只知道距离要跳转的地址有多少个字节来跳转 - jmp near ptr : 段内近转移,范围(-32769~32767),16位位移
- jmp far ptr : 会连CS:IP一起修改
jcxz,loop
条件转移 jcxz 标号,有条件转移,只有在CX为0时才会转移。当CX!=0时,程序将继续执行下面的指令。这样看来的话,loop指令其实也是一个条件转移指令,每次loop,cx递减1,直到cx为0时跳出循环。注:标号均为8位,范围为-128~127
ret,retf
ret是跳转前的指令,把IP压入读出栈,之后sp-=2,相当于POP IP
retf同等,之不过多了CS,差不多等于POP CS;SP-=2,POP IP;SP-=2
Call指令
Call 标号 ,把当前IP,push入栈之后,跳转到标号地址执行
执行过程为:sp-=2;((ss)x16)+sp = IP#把IP压入栈;IP=IP+16位位移
因为跳转是计算位移而不是更具物理地址跳转,所以16位位移地址 = 标号地址 - call指令之后的第一个地址
因为是16位,所以范围是-32768~32767
标志寄存器
- ZF 判断结果是否为0,执行结果为0,则ZF为1,反之
- PF 判断奇偶,偶数为1,基数为0
- SF 符号寄存器,判断是否带符号。
- CF 进位或者结尾标志,debug中,NC为没进位,CY为进位,对于无符号数来说才会存在
- OF 溢出标志位,对于有符号数来说才会存在
- DF 方向标志位,DF=0,si di都会递减,DF=1,si di都会递增
- TF 用来检测单步中断,如果TF=1则产生中断
ADC,SBB指令
- adc,才不是射手呢(doge)带进位加法指令,adc ax,bx 相当于 ax = ax + bx +CF
- SBB,有加法当然就有减法,带进位减法指令
cmp指令
对比指令,cmp a,b == a-b,只不过不记录结果
这时候我们可以看ZF位就可以进行对比,PF可以判断奇偶,看CF来判断两个大小,但是还要关注SF和OF来判断是否有溢出/进位
检测比较结果的转移指令
- je,等于则转移 ZF=1
- jne,不等则转移 ZF=0
- jb,低于则转移 CF=1
- jnb,不低于则转移 CF=0
- ja, 高于则转移 CF=0 ZF=0
- jna, 不高于则转移 CF=1 或ZF=1
movsb,movsw
功能是将ds:si中的内存单元指向es:di中然后更具DF进行sidi的递增或者递减
(果然我们计算机中的数据都是sb么2333
传送一个字就是movsw,区别就是每次递增或者递减sidi+-=2
可以配合rep指令使用,rep是更具CX重复执行指令
cld,std
有了上面那些,当然要对DF进行操作啦,然而肯定不能用ADD的说。所以就有了cld和std
cld 让DF=0,std让DF=1
CPU调用中断指令
也相当于执行N号中断
- 取中断类型码N
- push IF,TF
- push CS,IP
- IP=N4 CS=N4+2
lea
lea指令,格式:lea 目的寄存器,源操作数
作用:将源操作数的地址偏移量保存到目的寄存器中。学习lea指令可以和mov指令一起来记,他们格式相同,但mov指令是将操作数指向的内存中的数据保存到目的寄存器。
函数调用方式
//作用范围为VC++
- 首先是在上层函数,在调用函数之前,会先把参数从左到右push进栈
- 然后执行call函数,其中call函数又会隐藏触发一个压栈操作,会把IP压入栈
- 然后到了被调用函数,会先push ebp,把主函数的ebp保存
- 之后mov ebp,esp 更新EBP寄存器的值,更新完成后,被调用函数即可以使用EBP定位它的函数参数和局部变量
- 之后esp-00C,创建一片内存空间来保存函数状态
- 之后保存上层函数的ebx,esi,edi
- 之后在附加段寄存器创建一片空间(创建方式是为ECX赋值然后用rep stos循环写入
- 之后开始函数操作
- return操作其实是把值传给eax
- pop edi,esi,ebx
- mov esp,ebp 调整栈顶指针,使esp指向保存有main函数EBP的地址处,为恢复main函数ebp做准备
- pop ebp 正式恢复main函数的ebp
- ret 会触发一次栈出操作,会把最开始Call压入的IP弹出,然后程序开始执行IP所指向的地址
1920*1080的分辨率看你这个文章眼好疼苦QAQ
垃圾前端+垃圾审美=垃圾界面233333
好深啊 你学这东西!