一些东西


指令执行周期

取指令,译码,执行

加载执行程序

1
1.磁盘寻找文件 2.访问文件信息 3.加载程序之内存 4.执行指令,分配Process ID 5.进程自动运行 6.进程结束后从内存中移除

32位x86处理器

1
2
3
操作模式:保护模式,虚拟8086模式(保护模式子模式),实地址模式,系统管理模式

xmm寄存器

64位x86处理器

1
2
3
4
5
6
7
8
9
向后兼容x86指令集

地址长度64位,虚拟地址控件位264次方字节2

可以使用64位通用寄存器,运行指令具有64位整数操作数

x86多了8各通用寄存器

物理地址为48位,支持256TB的RAM
1
操作模式:兼容模式,64位模式    

I/O访问层次

1
2
3
4
高级语言函数
操作系统(os
BIOS
硬件

汇编语言基本元素

1
2
3
4
5
6
7
8
9
整数常量 0A3h16进制0 h) 19d10进制,可以不写)23q/o(八进制) 10011b(二进制)
实数常量 2 3.0 +3.0 -44.2E+5 26.E5
字符常量 ‘A’ "A"
字符串常量 “HELLO”
保留字 mov lea add sub jcc 寄存器 属性 db dword 运算符
标识符 第一个字符是有限制的,标识符不能与保留字相同
伪指令 data offset
指令 mov eax123
注释 ;

定义数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
整数:
BYTE 8位(无符号) SBYTE(有符号,汇编)
WORD 16位(无符号) SWORD(有符号)
DWORD 32位(无符号)SDWORD(有符号)
FWORD 48位(无符号)保护模式的远指针 SFWORD(有符号)
QWORD 64位 整数
TBYTE 80位 整数
实数:
REAL4 32位 短实数
REAL8 64位 长实数
REAL10 80位 拓展实数
伪指令:
db 8位整数 char ASCII
dw 16位整数
dd 32为整数或者实数
dq 64位整数或者实数
dt 80位的整数
大端序与小端序:
大:12345678
小:78563412

数据传送指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
mov eax,1
mov reg32,imm32
操作数类型
立即数;寄存器操作数 eax ebx;内存操作数

reg 通用寄存器
sreg 段寄存器
imm 立即数
mem 内存

mov 目的操作数,源操作数(两个位数相同,不能同时为内存操作数)
mov reg,reg
mov mem,reg
mov reg,mem
mov mem,imm
mov reg,imm
mov mem,mem 得写成 mov reg,mem mov mem reg
mov eax,cx 得写成 mov eax,FFFFFFFF mov axcx
eax = 101010101010101010
cx = 10101010
00000000110101010

movzx
movzx eaxcx 可以(全0拓展)
eax = 101010101010101010
cx = 10101010
0000000010101010

movsx
mov eaxcx
eax = 101010101010101010
cx = 10101010
111111111110101010

LAHF //加载标志位到AHax的高八位)中
lahf
mov flag(8位整数),ah

sahf //拷贝回标志位寄存器
mov ah,flag
sahf

xchg //交换指令
xchg reg,reg
xchg reg,mem
xchg mem,reg

加法与减法

1
2
3
4
5
6
7
8
9
add
add 操作数1 操作数2 (操作数类型和mov相同)

sub
sub 操作数1 操作数2(操作数类型和mov相同)

inc(自增) dec(自减)

neg 取反符号位也取

数据相关的运算符和伪指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.data
szStr db “hello word”,0
num dword 5
arrNum dword 012345
var1 db

offset 获取距离段起始位置的偏移
mov eax offset var1
mov eax offset arrNum + 4
mov eax,【eax】 //【】是取地址里面的内容,间接寻址

ptr 用来指定操作数的类型或尺寸
mov axword ptr num //取低十六位

type 返回当前元素大小

lengthof 返回数组中元素个数
mov eax,offset lengthof arrNum

sizeof 返回数组占的空间
mov eax,sizeof arrNum

间接寻址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
pbyte typedef ptr byte //typedef
.data
asd pbyte 1
var byte 012345678

xor eax, eax //清零
xor ebx, ebx
mov eax, offset var
mov bl, [eax]
inc eax //byte 是一个字节,加1到数组下一个元素
mov bl, [eax]
inc eax
... //完成遍历

xor eax, eax //清零
xor ebx, ebx
mov eax, offset var
mov bl, [eax]
mov bl, [eax + 1] //word +2, dword + 4
mov bl, [eax + 2]
...

mov esi, 4
mov eax,var[esi * 1] //1是数据宽度,结果取得是4

JMP和LOOP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
jmp //无条件跳转

ecxloop的计数器
xor eaxeax
mov ecx10
lp:
inc eax
loop lp

.data
source byte "hello world",0
target byte sizeof source dup(0)

main proc //执行拷贝
mov esi,0
mov ecx,sizeof source
lp:
mov al,source[esi * 1]
mov target[esi * 1],al
inc esi
loop lp
push 0
call ExitProcess
add esp4 //堆栈平衡

堆栈操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
栈:先进后出

push esp - 4
pop esp + 4

pushfd popfd32位标志位寄存器压入栈中

pushad popad 通用寄存器压栈
eax ecx edx esp ebp esi edi顺序压栈

pusha popa 16

字符串逆序
.data
source byte "hello world",0
sourcesize = ($ - source) - 1
.code
main proc
mov ecx,sourcesize
mov esi,0
lp1:
movzx eax,source[esi * 1] //数据传送指令MOV的变体。无符号扩展,并传送。
push eax
inc esi
loop lp1
mov ecx,sourcesize
mov esi,0
lp2:
pop eax
mov source[esi],al
inc esi
loop lp2
push 0
call ExitProcess
add esp,4
main ENDP
END main

定义函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
call 
1.eip压栈 2.jmp到函数处

ret
1.pop eip 2.jum eip

addx proc uses esi ecx
add esi,ecx
mov eax,esi
ret
addx ENDP

mian proc
mov esi,5
mov ecx,6
push esi
push ecx
call addx
main endp
end main

布尔与比较指令

1
2
3
4
5
6
7
8
9
10
11
test  //测试某位是不是1 运算逻辑就是and 不修改eax的值,改标志位寄存器
eflags
test eax 00000001

cmp //原理是相减 不修改操作数,修改标志位
cmp o1,o2
o1 > o2 // zf = 0, cf = 1 //无符号数 sf != of
o1 < o2 //zf = 0, cf = 0 //sf = of
o1 = 02 //zf = 1 ,cf = 0 //zf = 1
zf 零标志位; cf 进位标志位; sf 符号标志位; of 溢出标志位

条件跳转指令

JCC指令 解释 英文原文 检查符号位 应用
JZ 如果为0则跳转 jump if zero ZF = 1 if(i == 0)
JE 如果相等则跳转 jump if equal ZF = 1 if(i == j)
JNZ 若为0则不跳转 jump if not zero ZF = 0 if(i != 0)
JNE 若不相等则跳转 jump if not equal ZF = 0 if(i != j)
JS 若为负数则跳转 jump if sign SF = 1 if(i < 0)
JNS 若不为负数则跳转 jump if not sign SF = 0 if (i > 0)
JP/JPE 若1出现的次数为偶数跳转 jump if parity(even) PF = 1
JNP/JPO 若1出现的次数为奇数跳转 jump if not party(odd) PF = 0
JO 若溢出则为0 jump if overflow OF = 1
JNO 若无溢出则跳转 jump if not overflow OF = 0
JC 若进位则跳转 jump if carry CF =1 if(i < j)
JB 若低于则跳转 jump if below CF = 1 if(i < j)
JNAE 若不高于等于则跳转 jump if not above equal CF = 1 if (i < j)
JNC 若无进位则跳转 jump if not carry CF = 0 if(i > =j )
JNB 若不小于则跳转 jump if not below CF = 0 if(i >= j)
JAE 若高于等于则跳转 jump if above equal CF = 0 if(i >= j )
JBE 若小于等于则跳转 jump if above equal CF = 1或 ZF = 1 if(i <= j)
JNA 若不超过则跳转 jump if not above CF = 1或ZF =1 if(i <=j)
JNBE 若不小于相等则跳转 jump if not below equal
JA
JL
JNGE
JNL
JGE
JLE
JNG
JNL
JG

JCC指令 中文含义 英文原意 检查符号位 典型C应用
JZ/JE 若为0则跳转;若相等则跳转 jump if zero;jump if equal ZF=1 if (i == j);if (i == 0);
JNZ/JNE 若不为0则跳转;若不相等则跳转 jump if not zero;jump if not equal ZF=0 if (i != j);if (i != 0);
JS 若为负则跳转 jump if sign SF=1 if (i < 0);
JNS 若为正则跳转 jump if not sign SF=0 if (i > 0);
JP/JPE 若1出现次数为偶数则跳转 jump if Parity (Even) PF=1 (null)
JNP/JPO 若1出现次数为奇数则跳转 jump if not parity (odd) PF=0 (null)
JO 若溢出则跳转 jump if overflow OF=1 (null)
JNO 若无溢出则跳转 jump if not overflow OF=0 (null)
JC/JB/JNAE 若进位则跳转;若低于则跳转;若不高于等于则跳转 jump if carry;jump if below;jump if not above equal CF=1 if (i < j);
JNC/JNB/JAE 若无进位则跳转;若不低于则跳转;若高于等于则跳转; jump if not carry;jump if not below;jump if above equal CF=0 if (i >= j);
JBE/JNA 若低于等于则跳转;若不高于则跳转 jump if below equal;jump if not above ZF=1或CF=1 if (i <= j);
JNBE/JA 若不低于等于则跳转;若高于则跳转 jump if not below equal;jump if above ZF=0或CF=0 if (i > j);
JL/JNGE 若小于则跳转;若不大于等于则跳转 jump if less;jump if not greater equal SF != OF if (si < sj);
JNL/JGE 若不小于则跳转;若大于等于则跳转; jump if not less;jump if greater equal SF = OF if (si >= sj);
JLE/JNG 若小于等于则跳转;若不大于则跳转 jump if less equal;jump if not greater ZF != OF 或 ZF=1 if (si <= sj);
JNLE/JG 若不小于等于则跳转;若大于则跳转 jump if not less equal;jump if greater SF=0F 且 ZF=0 if(si>sj)


1

函数调用约定

是函数调用者和被调用的函数体之间关于参数传递、返回值传递、堆栈清除、寄存器使用的一种约定。

  • Cdecl

声明语法为:

1
2
int function (int a ,int b) //不加修饰就是C调用约定 
int __cdecl function(int a,int b)//明确指出C调用约定

cdecl–C Declaration的缩写,C语言缺省的调用约定

cdecl调用约定意味着:

  • 参数从右向左压入堆栈
  • 调用者负责清理堆栈
  • C调用约定允许函数的参数的个数是不固定的,这也是C语言的一大特色。
  • 仅在函数名前加上一个下划线前缀,格式为_functionname。
  • Stdcall

声明语法为:

1
int __stdcall function(int a,int b)

stdcall(pascal)–Standard Call的缩写,C++的标准调用方式
在Microsoft C++系列的C/C++编译器中,常常用PASCAL宏来声明这个调用约定,类似的宏还有WINAPI和CALLBACK。
一般WIN32的函数都是__stdcall

stdcall的调用约定意味着:

  • 参数从右向左压入堆栈
  • 函数自身清理堆栈
  • 函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸
  • fastcall

声明语法为:

1
int fastcall function(int a,int b)

fastcall调用约定意味着:

  • 函数的第一个和第二个DWORD参数(或者尺寸更小的)通过ecx和edx传递,其他参数通过从右向左的顺序压栈
  • 函数自身清理堆栈
  • 函数名修改规则同stdcall:函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸
  • thiscall

thiscall一C++类成员缺省的调用约定

thiscall是唯一一个不能明确指明的函数修饰,因为thiscall不是关键字。由于成员函数调用还有一个this指针,因此必须特殊处理,thiscall意味着:

  • 参数从右向左入栈

  • 如果参数个数不确定,this指针在所有参数压栈后被压入堆栈。如果参数个数确定,this指针通过ecx传递给被调用者。

  • 如果参数个数不确定,调用者清理堆栈,否则函数自己清理堆栈

  • 对于参数个数不定的情况下,类似cdecl,固定时类似于stdcall,

  • C++编译时函数名修饰约定规则:

  • __stdcall调用约定

以“?”标识函数名的开始,后跟函数名;

函数名后面以“@@YG”标识参数表的开始,后跟参数表;

参数表以代号表示:

X–void ,

D–char,

E–unsigned char,

F–short,

H–int,

I–unsigned int,

J–long,

K–unsigned long,

M–float,

N–double,

_N–bool,

PA–表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复…

参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;

参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。

例如:

1
2
int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z
void Test2() -----“?Test2@@YGXXZ
  • __cdecl调用约定:_

规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YA”。

  • __fastcall调用约定:_

规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YI”。

  • 函数调用约定导致的常见问题

如果定义的约定和使用的约定不一致,则将导致堆栈被破坏,导致严重问题,下面是两种常见的问题:

1.函数原型声明和函数体定义不一致

2.DLL导入函数时声明了不同的函数约定

调用函数的代码和被调函数必须采用相同的函数的调用约定,程序才能正常运行。


x32是x86架构的32位拓展,向后兼容于16位的x86架构。计算机的CPU一次最多能处理32位数据。,当然32位计算机通常也可以处理16位和8位数据。

x64是x86架构的64位拓展,向后兼容于16位及32位的x86架构。x64于1999年由AMD设计,AMD首次公开64位集以扩展给x86,称为“AMD64”。其后也为英特尔所采用。

x86是一个intel通用计算机系列的标准编号缩写,也标识一套通用的计算机指令集合,X与处理器没有任何关系,它是一个对所有*86系统的简单的通配符定义。

//x96dbg是安装x32dbg和x64dbg用的


各种数据类型字节数

数据类型字节数


伪指令又称为伪操作,它是在对源程序汇编期间由汇编程序处理的操作,它们可以完成如处理器选择、定义程序模式、定义数据、分配存储区、指示程序结束等功能。


博客相关

图片大小

1
<img src = xxx.png width=40% /> or <img src =xxx.png width=100 height=100/>

表格:

1
| 空格 | 空格 |

hexo博客不更新,把.deploy_git文件夹删除,再hexo g -d


作业,程序,进程和线程

进程

一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,一个运行的xx.exe就是一个进程。

线程

进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。

作业:

作业指用户在一次解决或是一个事务处理过程中要求计算机系统所做的工作的集合。作业由三部分组成,即程序、数据和作业说明书。一个作业可以包含多个程序和多个数据集。作业说明书在系统中生成一个称为作业控制块(job control block,JCB)的表格。该表格登记该作业所要求的资源情况、预计执行时间和执行优先级等。从而,操作系统通过该表了解到作业要求,并分配资源和控制作业中程序和数据的编译、链接、装入和执行等。

作业是由一系列有序的步骤组成的。作业的完成要经过作业提交、作业收容、作业执行和作业完成4个阶段。在执行一个作业可能会运行多个不同的进程。

需要说明的是,作业的概念主要用在批处理系统中,而且,在批处理系统中,作业是抢占内存的基本单位。也就是说,批处理系统以作业为单位把程序和数据调入内存以便执行。

程序:

程序是一组有序指令的集合,并存放于某种介质中,是一个静态概念。

进程:

进程是为使程序能并发执行,且为了对并发执行的程序加以描述和控制而引入的概念。

在了解进程前,先说明下进程实体。进程实体是由程序段、相关的数据段和PCB三部分组成,是一个能独立运行、独立分配资源和独立接受调动的基本单位。

现在来说明进程的定义:进程是进程实体的一次执行过程,是系统进行资源分配和调度的一个独立单位。它是一个动态概念。

线程:

随着多处理机系统的发展,提高程序的并发执行程度的要求越来越高。为提高系统的并发执行度,进而引入了线程的概念。线程是比进程更小的能独立运行的基本单位(故又称“轻型进程”),更好的提高了程序的并发执行程度充分发挥了多处理机的优势。


RAM是随机存取存储器(random access memory),是计算机内部存储器中的一种,也是其中最重要的,计算机和手机中一般把其叫做(运行)内存,它的速度要比硬盘快得多,所以用运行程序在RAM中,而存放运行时不用的数据则在硬盘中,什么时候需要数据,便把数据从硬盘中拿到内存,但同时RAM断电会丢失数据,所以我们电脑如果断电了就会丢失原来正在运行的数据。所以,手机中的RAM和电脑中的RAM的概念是相同的,RAM即内存越大,能同时在内存中执行的程序就越多,性能一般是越好的。

ROM是只读存储器(Read-Only Memory),也是计算机内部存储器中的一种,而硬盘是外部存储器所以对于大学学子来说,考试时你如果把这两个混为一种东西绝对是错误的,当然,如果出选择题让你选,那么BIOS应该是用到ROM的那个。那么ROM究竟是干什么的,ROM和硬盘是否就没有任何关系呢?这就要从其发展历程说起,早期,乃至现在,我们的主要存储介质都是磁性存储,也就是磁盘,分为硬盘和软盘,硬盘不太适合做移动存储,因为其磁头容易损坏,不耐摔,而且体积较大,就算是缩小容量仍然很难缩小其体积,软盘虽然用作移动介质还算方便,但软盘容量过于小,不够用,而光盘虽然容量大但不易擦写,同时体积也不够小,这时就很适合使用半导体存储介质——ROM和RAM,ROM用来嵌入电脑主板或者做移动存储介质就很合适了,其体积够小,提供的容量可以比光盘和软盘的大,速度也更快,但成本相对更高,而且早期的ROM因为技术不成熟所以无法擦写,出厂后就只能读数据,所以叫只读存储器,后来随着技术的发展,在ROM的基础上出现了新的半导体存储介质EPROM和EEPROM,这两种可擦写,这就不符合ROM的命名,但是由于是在ROM的技术上衍变出来的,所以延用了一部分原来的叫法,此时非易失的半导体存储介质开始得以广泛应用,被大量用于电脑主板的bios和嵌入式存储,而后来在这两种技术的发展上又发展出了NAND FLASH闪存,这就是我们现在用的U盘中用到的技术,同样,因为其体积小,容量和速度均不错,现在手机存储中的emmc颗粒也是用的这种技术,所以有手机厂商就把手机的存储容量约定俗成为ROM,其继承ROM断电不丢失数据的特性,而且有着较快的速度。

那么电脑硬盘和ROM有什么关系呢?由于ROM和硬盘都可以存储数据而且断电不会丢失,而有都广泛运用于电子产品中,所以有人就对两者产生了混淆。硬盘分为两种,一种是机械硬盘(即磁盘HDD),一种是固态硬盘(SSD),磁盘和ROM没什么关系,但是固态硬盘就不一样了,固态硬盘用到的颗粒也是基于NAND FLASH技术,和u盘以及手机存储有点相似,所以说硬盘和ROM还是有关系的,固态硬盘的存储颗粒是ROM技术发展的产物,但不能说ROM就是硬盘。


编译器就是将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”的程序。一个现代编译器的主要工作流程源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 目标代码 (object code) → 链接器 (Linker) → 可执行程序 (executables)


一些东西
http://example.com/2022/10/01/一些东西/
作者
luo
发布于
2022年10月1日
许可协议