汇编要点汇总

  1. 循环执行的过程

  2. 分支执行过程

  3. stos=storagestring

4.c规范(函数堆栈操作)

    push ebp

    mov ebp,esp

    sub esp,0C0h

    push ebx

    push esi

    push edi

       ...

    pop edi

    pop esi

    pop ebx

    mov esp,ebp

    pop ebp

5.带参函数(个数1),调用前:

    push ecx

  使用参数:

    mov eax,[ebp+8]

    为什么是+8?这是因为call 会导致一条指令进栈,在加上函数开始时的push ebp,所以+8才能取到函数的参数

  函数结束:

  add esp,4

6.变长指令的问题,系统并不是一次读入整条指令,而是先取指令的前面几位,再决定该次取指操作怎么进行

7.switch语句 基本上会出现cmp xxx je xxx 所有的分支判断都放在最前,后面是各分支要执行的内容

8.汇编里面没有枚举体和共用体,有的只是结构体和基础类型

9.数组的访问,通常你会碰到这样的代码

    mov eax,<我要取得数组元素的下标>

    imul eax,eax,<结构大小>

    mov ecx,<结构数组开始的地址>

    mov eax,dword ptr[ecx+eax];取数组元素内容放到eax

    Or 访问结构内部元素    

    mov ecx,dword ptr[ecx+eax+0Ch]

    这些汇编码都是解读时应该注意的标志性的代码

    二维数组转成汇编实际上是一个结构体数组

10.阅读汇编码时,可以将代码进行分类,F(函数调用相关)   C(流程控制代码)   D(数据操作,四则运算)

11.发行版本的汇编代码,会尽量去掉循环

12.如果返回值指向了在堆栈中开辟的内存,那么对该返回值的使用将会导致错误,因为堆栈中开辟的内存只在当前函数中有效

13.复杂类型(结构体,类)作为返回值时,先在函数外开辟内存,再将指针(eax)传入函数,函数返回时根据eax再在当前函数

   堆栈内存中做一份拷贝(也就是说当前堆栈中有两份同样的结构体实例)。

14.汇编指令的中括号表示偏移量,并且支持在中括号内的四则运算

15.远跳转是跨段跳转JMP or CALL

16.stos = store string

17.arpl=adjust prl

18.scas=search character among string

Compares the byte, word, or double word specified with the memory operand with the value in the AL, AX, or EAX register, and sets the status flags in the EFLAGS register according to the results. The memory operand address is read from either the ES:EDI or the ES:DI registers (depending on the address-size attribute of the instruction, 32 or 16, respectively). The ES segment cannot be overridden with a segment override prefix.

19. shr逻辑右移,左侧补0 sar算术右移左侧补符号位

20.test instructdent equal to and but it don't save the result only effect some bits of the flag register

21.IF中断标记位,响应中断时IF置为0,表示中断处理过程中不响应可屏蔽中断(除非中断处理程序又将IF置为1(sti or cli)),而不可屏蔽中断只要发生cpu不会理睬IF标记位直接转到中断处理程序,不可屏蔽中断的中断类型码始终是2

22.汇编语句的结构一定程度上反映了cpu进行数据操作的方式,这也是理解和记忆汇编语句的简便方法。

23.有时候你需要显性的指出要访问的内存单元的长度,类似于mov ax,[0]这种语句,因为第一个操作数ax是一个字长,所以会从内存中取两个字节的数据放到ax中,for the mov al,[bx] cause the operand al represent only one byte's size, so the [bx] represent one byte data to be got from the memory, for some special conditions, you must indicate the size of the memory unit obviously, e.g. add byte ptr [bx],2, if we don't specify the size of memory data to be added, cpu will unknow the actual data to be added value 2. Such as inc byte ptr ds:[0] is the same.

24.关于进位和借位,cpu在做加法和减法会牵扯到这两种情况,当然如果运算结果在寄存器容量范围之内,则不会影响CF标志位,但如果一旦影响到CF标志位,我们得到的结果是一个不完全的结果,比如mov al,98H  add al,al最后结果是130H显然超出了al的容量,但由于进位信息保存在了标志寄存器中,所以我们可以根据CF位的值连同al部分的值组合在一起来得到最终结果。此外cpu还直接提供了能够处理进位的加法指令adc和能够处理借位的减法指令sbb,实际上就是把进位标志带入到运算中,比如,adc ax,ax 等同于ax+ax+cf 原理类似于我们做竖式运算的时候进位规则。

 简记CF(C,醋,无,无符号运算)  OF(O,有,有符号运算),二者互不影响,像add指令它既有无符号加法的含义又有有符号加法的含义,所以会同时影响这两个标志位。

25. pushf,popf让我们有机会读取和修改标志寄存器中的内容。

26.那些个跳转指令i.e.那些影响CS IP寄存器的指令

 27.直接定址法

assume cs:code ds:data

data segment

a dw 2,3,5,89,29,2

b db 'sdsddsdsdsd'

table dw a,b

data ends

code segment

start:

code ends

end start

 注意上面几个标号,a b table它们后面没有冒号,这些标签直接代表了地址,使用的时候很像数组,a[bx],table[si]倒不是什么新的指令,只是觉得汇编编译器逐渐向高级语言特性靠拢了,可以这么理解,a、b就是一些普通数组,table就是一个指针数组

28.mul指令 如果是8位相乘则结果放在ax中,16位相乘则结果放在dx和ax中,因此乘法不会产生溢出

div防溢出的办法,其实也很简单ffffffff/1结果是ffffffff肯定要溢出的,因为一个16位的寄存器是放不下一个dword型数据的,那么我们可以做下转化变为(ffff*ffff+ffff)/1=(ffff/1)*ffff+ffff/1分成两个不会溢出的除法,然后再求和。

29.jmpi指令 可同时改变cs and ip 格式:jmpi xxx(ip),xxx(cs) retn=ret near 格式 retn 0x0ch相当于pop ip;add esp,0x0ch

30.lea 指令 lea 寄存器,内存单元 意为load effective address 也就是内存单元的相对偏移地址。lea dx [ax+bx+5];dx=ax+bx+5其实相当于mov指令,但mov不支持操作数中.的四则运算,而lea可以,更省时,更有效率,有时还可以代替简单的加法。

31.算术加减乘除指令 or xor and 指令 以及shift指令都能影响标志位,进过实际操作证明, cmp以及test指令也能影响标志位,cmp主要是令两个操作数相减 然后设置一些标志位,set指令和jxx指令就是根据这些标志位的信息完成对应的操作。

相信世界是平的
谨记四个字“修身养性”
大江东去浪淘尽英雄,再牛B的人物最后也是一掊土
向善不是目的,而是抚慰心灵,更多的感受幸福,感谢别人给你行善的机会
相信老子的话:万物生于有,有生于无,一切的道理都源于一个无法证明的假设
我是好是坏就自然而然的摆在那里,并不会因为别人的评价而改变什么,我也不需要别人用一张纸来说明我什么,世间最难得的是自由



支持大额赞助:
原文地址:https://www.cnblogs.com/sky-view/p/3246480.html