crl7-key 发表于 2020-11-14 13:56

汇编学习笔记

本帖最后由 crl7-key 于 2021-1-7 11:04 编辑

1.进制的定义
进制是由符号组成,可以自己定义,进位是指向后数一位。
二进制:由两个符号组成,分别是0 、1 逢二进一
八进制:由八个符号组成,分别是0、1、2、3、4、5、6、7 、逢八进一
十进制:由十个符号组成,分别是0、1、2、3、4、5、6、7、8、9、逢十进一
十六进制:由十六个符号组成,分别是0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F、逢十六进一
当然,除了常规的,还有3进制、4进制....n进制,进制的符号不一定是常规的123顺序排列的。
主要作用可以用于加密。进制运算结果本质是通过查表得到的。

汇编的模式
16位汇编:实模式,16位处理器内的内部,最多可以处理存储的长度为16位。
32位汇编:保护模式,32位处理器内的内部,最多可以处理存储的长度为32位。
64位汇编:保护模式,64位处理器的内部,最多可以处理存储的长度位64位。


位数通用寄存器 扩展
16位通用寄存器 AX、BX、 CX、 DX、 SI、 DI、 BP、 SP R8W、R9W、R10W、R11W、R12W、 R13W、R14W、R15W
32位通用寄存器 EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP R8D、R9D、R10D、R11D、R12D、 R13D、R14D、R15D
64位通用寄存器 RAX、RBX、RCX、RDX、RSI、RDI、RBP、RSP R8、R9、R10、R11、R12、 R13、R14、R15


基本执行环境
32位 :8个32位通用寄存器,标志寄存器EFLAGS ,指令指针寄存器EIP
64位:16个64位通用寄存器,标志寄存器RFLAGS,指令指针寄存器RIP

2. 常用寄存器结构
eax : 累加器,操作数和结果数据累加器,返回值运算结果一般都存储在这里
ebx : 基地址,DS段的数据指针,在内存寻址的时候存放基地址
ecx : 计数器,字符串和循环操作的计数器
edx : 用于存储部分乘法结果和部分除法被除数
ebp : 基址指针,SS段的数据指针
esp : 栈帧指针,一般指向栈顶,所以也被称为栈顶指针
edi : 字符串操作的目标指针,ES段的数据指针
esi :字符串操作的源指针,SS段的数据指针

EFLAGS寄存:包含了独立的二进制位,用于控制CPU操作,或是反应一些CPU操作的结果。有些指令可以测试和控制这些单独的处理器标识位。
EFLAGS寄存器的状态标志(0、2、4、6、7以及11位)指示算术指令(如ADD, SUB, MUL以及DIV指令)的结果,这些状态标志的作用如下:
**CF(bit 0) **   若算术操作产生的结果在最高有效位(most-significant bit)发生进位或借位则将其置1,反之清零。这个标志指示无符号整型运算的溢出状态,这个标志同样在多倍精度运算(multiple-precision arithmetic)中使用。
**PF(bit 2) **:   如果结果的最低有效字节(least-significant byte)包含偶数个1位则该位置1,否则清零。
**AF(bit 4) **:   如果算术操作在结果的第3位发生进位或借位则将该标志置1,否则清零。这个标志在BCD(binary-code decimal)算术运算中被使用。
**ZF(bit 6) **:   若结果为0则将其置1,反之清零。
**SF(bit 7) **:   该标志被设置为有符号整型的最高有效位。(0指示结果为正,反之则为负)
**OF(bit 11) **:   如果整型结果是较大的正数或较小的负数,并且无法匹配目的操作数时将该位置1,反之清零。这个标志为带符号整型运算指示溢出状态。
在这些状态标志中,只有CF标志能够通过使用STC, CLC以及CMC指令被直接修改,或者通过位指令(BT, BTS, BTR以及BTC)将指定的位拷贝至CF标志中。
**DF标志(DF flag)**:这个方向标志(位于EFLAGS寄存器的第10位)控制串指令(MOVS, CMPS, SCAS, LODS以及STOS)。设置DF标志使得串指令自动递减(从高地址向低地址方向处理字符串),清除该标志则使得串指令自动递增。STD以及CLD指令分别用于设置以及清除DF标志。
MMX寄存器:在实现高级多媒体和通信应用时,MMX技术提高了Intel处理器的性能。8个64位MMX寄存器支持成为SIMD的特殊指令。顾名思义,MMX指令对MMX寄存器中的数据值直接进行并行操作。虽然它们看上去是独立的寄存器。但是MMX寄存器实际上是浮点单元中使用的同样寄存器的别名。

3.visual studio 2015编写汇编
1.建立一个空项目
2.选中项目右键 ”生成自定义“,选择MASM生成规则
3.新建一个.asm后缀的文件
4.选中项目右键 - > 属性 - > 链接器 - > 系统 - > 子系统选<控制台(SUBSYSTEM:CONSOLE)>
5.选中项目右键- > 属性 - > 链接器 - > 高级 - > 入口点填 "main"

4 .汇编基本使用
4.1加法
加法指令ADD(Addition)
格式:ADD OPRD1,OPRD2
功能:两数相加
加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响
不允许OPRD1与OPRD2同时为存储器
带进位加法指令ADC(Addition Carry)
格式:ADC OPRD1,OPRD2
功能:OPRD1 = OPRD1 + OPRD2 + CF

4.2 减法
减法指令SUB(SUBtract)
格式:SUB OPRD1,OPRD2
功能:两个操作数的相减,即从OPRD1减去OPRD2,其结果放在OPRD1中,指令的类型及标识位的影响与ADD指令相同,注意立即数不能用于目的操作数,两个存储器操作数之间不能直接相减,操作数可为8位或16位的无符号数或符号数
带错位减法指令SBB(SuBtract with Forrow)
格式:SBB OPRD1,OPRD2
功能:进行两个操作数的相减再减去CF进位标志位,即从OPRD1 = OPRD1 - OPRD2- CF,其结果放在OPRD1中

4.3 乘法
无符号数指令MUL(MULtiply)
格式:MUL OPRD
带符号数指令IMUL(Integer MULtiply)
功能:乘法操作
OPRD为通用寄存器或存储器操作数
本指令会影响标志位CF及OF

## 除法
无符号数除法指令DIV(DIVision)
格式:DIV OPRD
功能:实现两个无符号二进制数除法运算
带符号数除法指令IDIV(Integer DIVision)
格式:IDIV OPRD
功能:实现两个带符号数的二进制除法运算
比如16bit 的被除数,分别存在2个8bit寄存器AH:AL,商放在AL,余数在AH
比如32bit 的被除数,分别存在16个8bit寄存器DX:AX,商放在AX,余数在DX
比如64bit 的被除数,分别存在32个8bit寄存器EDX:EAX,商放在RAX,余数在EDX
比如128bit 的被除数,分别存在64个8bit寄存器RDX:RAX,商放在RAX,余数在RDX

4.4 自增
加1指令INC(INCrement by 1)
格式:INC OPRD
功能:OPRD = OPRD + 1

4.5 自减
减一指令DEC(Decrement by 1)
格式:DEC OPRD
功能:OPRD = OPRD -1



4.6 loop指令
循环控制指令LOOP
格式:loop 标号
功能:(CX)<---(CX)-1,(CX)<>0,则转移至标号处循环执行,直至(CX)=0,继续执行后指令

.586
.MODEL flat,stdcall
.code
main proc
    mov eax,1
    mov ebx,1
    mov ecx,10
s:
    add eax,ebx
    loop s
    mov eax,eax
main ENDP
END main
   
    //1+2+3 +....+1000
    .586
.MODEL flat,stdcall
.code
main proc
    move eax,0
    move ecx,100
s:
    add eax,ecx
    loop s
    move eax,eax
main ENDP
END main

什么是堆栈?
1. 栈是一个后进先出的存储区域,位于堆栈段中,SS段寄存器描述的就是堆栈段的段地址
2. 栈的数据出口位于栈顶,也就是esp寄存器所指向的位置
3. 栈顶x低位,也就是地址较小的一侧,由ebp寄存器指向的栈低,并不会改变

4.7 栈操作指令
PUSH:压栈指令,32位汇编首先ESP-4,留出一个空间,然后把要压入栈中的内容压入
POP:出栈指令,32位汇编首先将栈顶的数据弹出给指定的目标,然后ESP+4,清掉空间
4.8 MOV指令
数据传送指令 MOV
格式:MOV OPRD1,OPRD2
功能:将一个源操作数送到目的操作数中,即OPRD1<--OPRD2
说明:
OPRD1为目的操作数,可以说寄存器、存储器、累加器
OPRD2为源操作数,可以数寄存器、存储器、累加器和立即数。

.586
.MODEL flat,stdcall
.code
main proc
    mov eax,ebx
    mov eax,ecx
    mov ecx,0
    mov eax,eax
main ENDP
END main

4.9 LEA
有效地址传送指令
格式:LEA OPRD1,OPRD2
功能:将源操作数给出的有效地址传送到指定的寄存器中
OPRD1必须是寄存器

.586
.MODEL flat,stdcall
.code
main proc
    lea eax,dword ptr ss:
    mov eax,eax
main ENDP
END main

4.10 XCHG
数据交换指令
格式:XCHG OPRD1,OPRD2,其中OPRD1为目的操作数,OPRD2为源操作数
功能:将两个操作数相互交换位置,该指令把源操作数OPRD2与目的操作数OPRD1交换

.586
.MODEL flat,stdcall
.code
main proc
    xchg eax,dword ptr ss:
    mov eax,eax
main ENDP
END main

4.11 CMP指令
比较指令CMP(ComPare)
格式:CMP OPRD1,OPRD2
功能:对两数进行相减,进行比较

.586
.MODEL flat,stdcall
.code
main proc
    mov eax,5
    mov ebx,4
    cmp eax,ebx
    cmp eax,4
    mov eax,eax
main ENDP
END main

4.12 TEST
测试指令
格式:TEST OPRD1,OPRD2
功能:其中OPRD1、OPRD2的含义同AND指令一样,也是对两个操作数进行按位的‘与‘运算,----唯一不同之处是不讲’与‘的结果送目的操作数,即本指令对两个操作数的内容均不进行修改,仅数载逻辑与操作后,对标志位重新置位

4.13 常用的JCC指令
JMP:无条件跳转
JZ/JE:ZF = 1等于0或相等调整
JNZ/JNE:ZF = 0 不等于0或者不相等跳转
JBE/JNA:CF = 1/ZF = 1 低于等于或者不高于跳转
JNBE/JA:CF = 0 / ZF = 0 不低于等于/高于跳转
JL/JNGE:SF != OF 小于/不大于等于跳转
JNL/JGE:SF = OF 不小于/大于等于跳转

4.14 MOVS指令
字符串传送指令MOVS
格式:MOVS OPRD1,OPRD2
---MOVSB
​   MOVSW
功能:OPRD1<---OPRD2
说明:
1. 其中OPRD2为源串符号地址
2. OPRD1为目的串符号地址

4.15 STOS指令
字符串存储指令
格式:STOS OPRD
功能:把AL(字节)或AX(字)中的数据存储到DI为目的串地址指针所寻址的存储器单元中去指针DI将根据DF的值进行自动调整

4.16 REP指令
重复前缀的说明
格式:REP                ;CX<>0重复执行字符串指令
​         REPZ/REPE    ;CX<>0且ZF = 1重复执行字符串指令
​         REPNZ/RPNE ; CX<>0且ZF = 1重复执行字符串指令
功能:在串操作指令前加上重复前缀,可以对字符串进行重复处理,由于加上重复前缀后,对应的指令代码是不同的,所以指令的功能便具有重复处理的功能,重复的次数存放在CX寄存器中
4.17 CALL指令
过程调用指令
格式:CALL OPRD
功能:过程调用指令
相当于:
​         push eip
​         amp OPRD
4.18 RETN指令
返回指令,相当于:
​         pop eip
​         jmp eip
4.19 过程调用-函数
过程调用的方式:
​       function proc
​         code
​       function endp
参数传递方式:
1. 寄存器传参
2. 堆栈传参

.586
.MODEL flat,stdcall
.code
addx proc
      add eax,ebx
addx endp
main proc
      mov eax,1
      mov ebx,2
      call addx
      mov eax,eax
main ENDP
END main


.586
.MODEL flat,stdcall
.code
addx proc
      mov eax,
      mov ebx,
      add eax,ebx
      ret
addx endp
main proc
      push 1
      push 2
      call addx
      mov eax,eax
main ENDP
END main


5. Win32 第一个hello world程序

.586
.MODEL flat,stdcall
includelib user32.lib
includelib kernel32.lib
ExitProcess PROTO,dwExitCode:DWORD
MessageBoxA PROTO hWnd:DWORD,IpText:BYTE,IpCaption:BYTE,uType:DWORD
.data
string db "hello word!",0
.code
main proc
    push 0
    lea eax,string
    push eax
    push eax
    push 0
    call MessageBoxA
    add esp,16;堆栈平衡,push一个dword4个字节,一共push了4个,共16个字节
    call ExitProcess
main ENDP
END main


移情√似水 发表于 2020-11-14 14:16

学习了,谢谢

ntwmkpx 发表于 2020-11-14 14:29

不错。好好整理一下就更好了~感谢分享。

Peter19 发表于 2020-11-14 14:29

学习了,谢谢,很详细

zsxm6865 发表于 2020-11-14 15:03

学习了!{:1_927:}

jenson1 发表于 2020-11-14 15:20

学习了,对新手很有用,谢谢

WD丶活着 发表于 2020-11-14 15:42

52是精准推荐吧,昨天搜CE,汇编,今天就几个贴

鸭子咯咯哒~ 发表于 2020-11-14 16:24

wow,好棒!希望多发多点{:1_887:}

异界封侯 发表于 2020-11-14 16:27

不错,学习了

童子晴 发表于 2020-11-15 16:03

谢谢已经学习到了。
页: [1] 2
查看完整版本: 汇编学习笔记