汇编基础总结

本文讨论的是32位intel处理器的汇编
image.png

单位

因为计算机本质是二进制的电平01因此最小底层的单位是位bit,一位只有两种状态0/1;而一般而言,为了保证有储存的信息量有一定程度计算机对数据的储存一般是以1字节byte(8位)作为最小储存单位;而为了方方便显示查看一般将每个字节转换位十六进制表示,也就是两位十六进制表示。

在汇编中常见的单位

  • byte 字节 8位二进制 2位十六进制
  • word 字
关键字中文名二进制长度十六进制从长度
bit1四位才有一个长度
byte字节82
word164
dword双字328

而对一般而言的32位处理器,即代表32个bit,4个byte,2个word,一个dword。

位运算指令

汇编中的指令使用分为指令名和操作数

指令名 操作数1,操作数2

代表初始值位操作数1然后经过指令使用操作数2进行变换之后把结果保存到操作数1类似操作数1+=操作数2操作数1=操作数2

一般来说:大部分的汇编指令两个操作数不能同时为内存,一般默认这种情况,如有特殊会说明

基本含义汇编表示C语言表示
与 a&band a,ba&=b
或 a\bor a,ba\=b
异或 a^bxor a,ba^=b
非 ~anot aa~=a
加 +add a,ba+=b
减 -sub a,ba-=b
自增 in-countinc aa++
自减 de-countdec aa--

通用寄存器

完整显示形式

汇编中对于寄存器的操作是直接使用寄存器名称的

类似寄存器的变量名

寄存器特殊用途(约定俗成)编号
EAX~0
ECX~1
EDX~2
EBX~3
ESP存储内存中栈顶的地址4
EBP存储内存中栈底的地址5
ESI 6
EDI 7

其他显示形式

EAX ECX EDX EBX的E代表者32位

用十六进制表示就是AA BB CC DD(从左到右,从高到低位——

为了向下兼容16位,8位有如下的显示方式

去掉E就是低位的十六位,也就是四个十六进制,例如

AX CX DX BX:CC DD

而低位的十六位可以分为两个八位高位High,低位Low,即在十六位表示的基础上把X替换成对应高低位表示,例如

  • AH CH DH BH:CC
  • AL CL DL BL:DD

标志寄存器

各位简介

OD中的寄存器窗口

  • EIP始终指向当前程序运行到哪一行代码的代码地址
  • C位(Carry Flag 进位标志) :更准确的来说是无符号数是否溢出的
  • P位(Parity Flag):也就是,运算结果中二进制表示的数据,1个数的奇偶

    • 偶数个1:为1
    • 奇数个1:为0
  • A位(Auxiliary Carry Flag 辅助进位标志):运算结果中半个数据宽度的低位组的最高位是否进位或借位

    • 发生进位或者借位为1,不发生则为0
    • 例如0000 1000变成0001 0000那么就发生了进位A=1
    • 例如0001 0000变成0000 1000那么就发生了进位A=1
  • Z位(Zero Flag零位标志):运算结果是否为0

    • 是0标志为1
    • 是1标志位0
  • S位(Sign Flag符号标志):数值等于运算结果的最高位

    • 因此如果把运算结果当作有符号数
    • S=1则运算结果为负数,反之为正数
    • 如果当作无符号数则这个标志位是没有意义的
  • O位(Overflow Flag溢出标志位):更准确的来说是代表有符号数是否溢出的标志

*C,O位区分

  • 作为无符号数运算看:C位

    • 字面意义上理解的是否有溢出数据宽度
  • 作为有符号数运算看:O位

    • 正加正为负(首位变为1)则溢出
    • 负加负为正(首位变为0)则溢出
    • 负加正 无论如何不溢出,因为不可能超过数据宽度

储存指令

共性

  • 立即数:即数字一般用十六进制表示如0xFFFFFF
  • 寄存器:即上一个标题讲的内容,用寄存器名称表示
  • 内存:单位 ptr ds:[地址]

    • 单位只有byteworddword
    • 地址一般用十六进制表示
    • 这个表示过程就相当于对[]的地址进行寻址

mov:=

  • 本质上是赋值
  • 除了内存到内存的赋值不能使用它其余的三种数据都可以随意储存

例如

mov eax,ebx
mov dx,cx
mov bl,cl

lea:a=&b

  • 本质上是取址保存

例如

mov eax,ebx
xor eax,ebx
;等价于 mov edx,eax*2+ebx
;也就是先*后&
lea edx,byte ptr ds:[eax*2 + ebx]

push:入栈

  • 规范:push 存入的数。这样会存入对应宽度的数到达栈顶
  • 数据宽度为32位(dword,八个十六进制),16位(word,四个十六进制)不能更小

    • 但是有例外:立即数可以存入最小8位的也就是一个字节byte
  • 内存中最小的地址单位是byte,8位(两个十六进制)

pop:出栈

  • 规范:pop 取出的数存入的位置。这样会取出对应宽度的数存道对应的位置
  • 取出的数据宽度为32位(dword,八个十六进制),16位(word,四个十六进制)不能更小
push 0xFFFFFFFF
push 0xAAAAAAAA

pop eax ;取出的是0xAAAAAAAA
pop ebx ;取出的是0xFFFFFFFF

pushad和popad

  • 无操作数
  • pushad是吧寄存器的数值存入栈顶
  • popad是吧栈顶的的数值8组32位(8x8=64个地址)的值存入寄存器
  • 如果pushad后和popad前的栈顶位置相同,那么具有还原寄存器原有数值的功能,这也被称为堆栈平衡

跳转指令

jmp:无条件跳转

  • 本质是修改EIP的值,因为EIP代表程序下一步指向的指令地址,所以代表着跳转
  • 规范:jmp 指令地址。指令地址可以用寄存器或者立即数表示

call:一般用于函数调用

  • 步骤

    1. 计算并且保存jmp前的下一行代码的地址,并push进栈中
    2. jmp到对应地址
    3. 继续执行
    4. 直到retn(return)

      1. pop eax
      2. jump eax

cmp:相等与否

  • 本质:是sub指令但是不修改数值只是修改标志
  • 如果相同:则Z位标志为会变成1,即相减等于0

test:检查是否全为0

  • 本质:and指令但是不修改数值只修改标志
  • 例如test eax,eax
  • 如果为空:则Z位标志为会变成1,即相减等于0

根据符号位的条件条件跳转

我也没记,用的的时候现查,用多了就记住了https://blog.csdn.net/xuehuafeiwu123/article/details/77480167

Last modification:June 29, 2021
如果觉得我的文章对你有用,请随意赞赏。咖啡(12RMB)进度+100%,一块巧克力(1RMB)进度+6%。
(赞赏请备注你的名称哦!后台记录中来自理工小菜狗)