汇编学习笔记第一次
汇编学习笔记第一次
感谢乐哥能花费时间和精力来带带弟弟,弟弟一定努力
借着这次机会,刚好复习复习汇编的知识,将其熟练。
1 | hint: |
先巩固下基础知识
16位寄存器
指令 | 描述 |
---|---|
AH累加器(Accumulator) AL | 可用于乘、除、输入/输出等操作(在乘除指令中指定用来存放操作数) |
BH基地址寄存器(Base Register) BL | 在计算存储器地址时,可作为基址寄存器使用。 |
BL | |
CH计数寄存器(Count Register) CL | 在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数; |
CL | |
DH数据寄存器(DataRegister) DL | 在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。在16位CPU中,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址,但在32位CPU中,其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果,而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。 |
DL |
32位寄存器
指令 | 描述 |
---|---|
eax | EAX被称为32位累加器 |
ecx(计数寄存器) | ECX中的C即Count(计数之意)。在许多指令中,ECX、CX、CL被用作计数器。 |
edx(数据寄存器) | EDX中的D即Data(数据之意)。在进行乘法等运算时,常用EDX与EAX或DX与AX的组合来存放一个4字数或双字数。此外,DX也用来存放I/O端口地址。 |
ebx(基址寄存器) | EBX中的B即Base(基址之意)。EBX与BX常用来表示内存地址,现在所使用的PC中地址都是较大的整数,一般不会是8位,所以BL就不常使用了。 |
esp | ESP或SP用来指示堆栈段中的栈顶地址。一般情况下不使用ESP或SP做算术运算。 |
ebp | EBP和BP常用来存放内存地址,它们在默认情况下指向堆栈段中的存储单元。 |
esi | ESI或SI在串指令中表示源数据串的地址。 |
edi | EDI或DI在串指令中表示目的数据串的地址。 |
eip | 指令指针EIP、IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量。 |
eflags(Flags Register) | 。标志寄存器也称为程序状态寄存器或状态寄存器。指令指针和标志寄存器不能用作指令的操作数,它们是由CPU直接操纵的。特别地,EIP和EFLAGS的低16位分别由IP和FLAGS标识。 |
cs(Code Segment Register)代码段寄存器 | 其值为代码段的段值; |
ss(Stack Segment Register)堆栈段寄存器 | 其值为堆栈段的段值; |
ds(Data Segment Register)数据段寄存器 | 其值为数据段的段值; |
es(Extra Segment Register)附加段寄存器 | 其值为附加数据段的段值; |
fs(Extra Segment Register)附加段寄存器 | 其值为附加数据段的段值; |
gs(Extra Segment Register)附加段寄存器 | 其值为附加数据段的段值。 |
64位寄存器
指令 | 描述 |
---|---|
rax | 与32位类似 |
rbx | 与32位类似 |
rcx | 与32位类似 |
rdx | 与32位类似 |
rsi | 与32位类似 |
rdi | 与32位类似 |
rbp | 与32位类似 |
rsp | 与32位类似 |
r8 | 与32位类似 |
r9 | 与32位类似 |
r10 | 与32位类似 |
r11 | 与32位类似 |
r12 | 与32位类似 |
r13 | 与32位类似 |
r14 | 与32位类似 |
r15 | 与32位类似 |
rip | 与32位类似 |
eflags | 与32位类似 |
cs(Code Segment Register)代码段寄存器 | 其值为代码段的段值; |
ss(Stack Segment Register)堆栈段寄存器 | 其值为堆栈段的段值; |
ds(Data Segment Register)数据段寄存器 | 其值为数据段的段值; |
es(Extra Segment Register)附加段寄存器 | 其值为附加数据段的段值; |
fs(Extra Segment Register)附加段寄存器 | 其值为附加数据段的段值; |
gs(Extra Segment Register)附加段寄存器 | 其值为附加数据段的段值。 |
寻址方式
寻址方式 | 示例 | 操作对象 |
---|---|---|
立即寻址 | 1000h | 1000h这个数字 |
直接寻址 | [1000h] | 内存1000h地址的单元 |
寄存器寻址 | RAX | RAX这个寄存器 |
寄存器间接寻址 | [RAX] | 以RAX中存的数作为地址的内存单元 |
基址寻址 | [RBP+10h] | 将RBX中的数作为基址,加上10h,访问这个地址的内存单元 |
变址寻址 | [RDI+10h] | 将RDI作为变址寄存器,将其中的数字加上10h,访问这个地址的内存单元 |
基址加变址寻址 | [RBX+RSI+10h] | 逻辑同上 |
常见基础指令
指令类型 | 操作码 | 指令示例 | 对应作用 |
---|---|---|---|
数据传送指令 | mov | mov rax,rbx | rax = rbx |
mov qword ptr [rdi],rax | *(rdi) = rax | ||
取地址指令 | lea | lea rax,[rsi] | rax = & *(rsi) |
算术运算指令 | add | add rax,rbx | rax += rbx |
add qword ptr [rax],rax | *(rdi) += rax | ||
sub | sub rax,rbx | rax -= rbx | |
逻辑运算指令 | and | and rax,rbx | rax &= rbx |
xor | xor rax,rbx | rax ^= rbx | |
函数调用指令 | call | call 0x401000 | 执行0x40100地址的函数 |
函数返回指令 | ret | ret | 函数返回 |
比较函数 | cmp | cmp rax,rbx | 根据rax与rbx比较的结果改变标志位 |
无条件跳转函数 | jmp | jmp 0xa01000 | 跳到0x401000地址执行 |
栈操作指令 | push | push rax | 将rax的值压入栈中 |
pop | pop rax | 从栈上弹出一个元素放入rax |
标志寄存器
名称 | 标志 | 含义 |
---|---|---|
AF | 辅助进位标志 | 当运算结果在第3位进位 |
PF | 奇偶效验标志 | 当运算结果的最低有效字节有偶数个1时置1 |
SF | 符号标志 | 有符号整形的符号位为1时置1,代表这是一个负数 |
ZF | 零标志 | 当运算结果为全零时置1 |
OF | 溢出标志 | 运算结果在被操作数是有符号数且溢出时置1 |
CF | 进位标志 | 运算结果向最高位以上进位时置1,用来判断无符号数的溢出 |
常见判断指令
指令 | cmp a,b 条件(成立就跳转) | flag条件 |
---|---|---|
jz/je | a = b | ZF = 1 |
jnz/jne | a != b | ZF = 0 |
jb/jnae/jc | a < b 无符号 | CF = 1 |
ja/jnbe | a > b 无符号 | |
jna/jbe | a <= b 无符号 | |
jnc/jnb/jae | a >= b 无符号 | CF = 0 |
jg/jnle | a > b 有符号 | |
jge/jnl | a >= b 有符号 | |
jl/jnge | a < b 有符号 | |
jle/jng | a <= b 有符号 | |
jo | OF = 1 (运算结果在被操作数的是有符号数且溢出时置1) | |
js | SF = 1 (这是个负数) |
局部变量
人们把每个函数自己的这一片区域称为帧,由于这些帧都在栈上,所以又被称为栈帧,然而栈的内存区域并不一定是固定的,而且随着每次调用路径不同,栈帧的位置也会不同。虽然栈的内容随着进栈和出栈会一直不断变化,但是一个函数中,每个局部变量相当于该函数栈帧的偏移,都是固定的,所以可以引入一个寄存器来专门存储当前栈帧的位置,即用ebp,称为帧指针。程序在函数初始化阶段赋值ebp为栈帧中间的某个位置,这样可以用ebp引用所有的局部变量,由于上一层的父函数也要用ebp,因此要在函数开始时先保存ebp,再赋值ebp为自己的栈帧的值。
1.简单赋值
EBP:栈底寄存器,存放了指向函数栈帧栈底的地址
ESP:栈顶寄存器,存放了指向函数栈帧栈顶的地址
EIP:指令寄存器(程序计算器),存放CPU将要执行的指令
RIP:是保存了当前的程序的指针,加上偏移,就可以索引到静态变量的空间。
rsp: 是随时可能变化的(64位的函数调用)
rbp: 来作为参数和局部变量的基址(64位的函数调用)
1 qword = 2 dword = 4 word = 8 Byte = 64 bit eg:’1’ = 0x31
第一题
1 | 55 push rbp ;将函数(比如main)的栈底压到栈 |
1 |
|
这题就复习复习下一汇编语言
着重分析一下
汇编书中我们是用 ebp 和 esp
而在实际应用环境中,程序是64位的,就需要用rbp和esp来代替32位的ebp和esp寄存器。
rbp指向函数入口上堆栈的顶部,x86的堆栈朝向低地址;
所以访问地址为rbp的负地址[rbp-0x8]
第二题
1 | 55 push rbp ;将函数(比如main)的栈底压到栈 |
1 |
|
第三题
1 | 400457: 55 push rbp |
1 |
|
附加题
1 | 400457: 55 push rbp |
1 |
|
感谢Prowes5师傅
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Sunqiz's Blog!