C-正向基础

指令扩展

movsx

用于有符号数的类型转换

可以将大小不同的寄存器al的值传给cx,高位根据al的符号位是1,就全补1,是0就全补0

movsx cx,al

movzx

用于无符号数的类型转换

可以将大小不同的寄存器al的值传给cx,高位直接补0

movzx cx,al

sete

如果上一条表达式的判断结果为相等,会把cl设置为1,否则就不变,使用之前一般会把ecx整个寄存器异或自己置为0

sete cl

类型转换

注意有符号数与无符号数的区别,使用的汇编指令不同

低宽度转高宽度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "stdafx.h"


void add()
{
char x=0xf0;
int y=x;

}

int main(int argc, char* argv[])
{
add();
return 0;

}

image-20231106093036161

高宽度转低宽度

直接截取低宽度相应大小的低位数据,高位数据会被丢弃

表达式

1、只有一个结果

2、通常与流程控制语句或者赋值语句一起出现

3、当表达式存在不同宽度的变量时,结果将转换为宽度最大的那个

语句与程序块

语句影响了cpu与内存的分配,表达式没有

分支语句的{}内的语句被称为程序块,一个条件可以控制多个带分号的语句

参数

程序在运行的时候需要用到函数外面的值,这些值就需要借助参数进行传递;

返回值

如果函数不加return,调用函数的时候是无法接受参数值的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "stdafx.h"


int add(int x,int y)//x,y被称为形式参数,没有具体的数值
{
int z = x+y;
return z;//z作为局部变量在函数运行结束就会被销毁,为了使用改变量需要借助寄存器给他返回出去值
}

int main(int argc, char* argv[])
{
int a=add(1,2);//函数调用的时候传递的数值被称为实际参数,有具体的数值
printf("%u\n",a);
return 0;

}

关系运算符

结果只会返回0或者1

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
	==
!=
>=
<=
>
<


#include "stdafx.h"


void add()
{
int x=1;//mov dword ptr [ebp-4],1
int y=1;//mov dword ptr [ebp-8],1
int z = x==y;
//mov eax,dword ptr [ebp-4]
//xor ecx,ecx 清零ecx寄存器
//cmp eax,dword ptr [ebp-8]
//sete cl 如果比较结果想等就给cl赋值1
//mov dword ptr [ebp-0Ch],ecx
}

int main(int argc, char* argv[])
{
add();
return 0;

}

逻辑运算符

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
&&
||
!

#include "stdafx.h"


void add()
{
int x=3;
int y=2;
int z=1;
if(x>y&&y>z&&z==1)//所有条件都成立才执行
{
printf("OK");
}
}

int main(int argc, char* argv[])
{
add();
return 0;

}

0040B7C8 mov dword ptr [ebp-4],3
0040B7CF mov dword ptr [ebp-8],2
0040B7D6 mov dword ptr [ebp-0Ch],1
0040B7DD mov eax,dword ptr [ebp-4]
0040B7E0 cmp eax,dword ptr [ebp-8]
0040B7E3 jle add+50h (0040b800)//如果小于等于直接跳过,否则继续执行
0040B7E5 mov ecx,dword ptr [ebp-8]
0040B7E8 cmp ecx,dword ptr [ebp-0Ch]
0040B7EB jle add+50h (0040b800)//如果小于等于直接跳过,否则继续执行
0040B7ED cmp dword ptr [ebp-0Ch],1
0040B7F1 jne add+50h (0040b800)//如果不等于直接跳过,否则继续执行
0040B7F3 push offset string "%u\n" (0042001c)
0040B7F8 call printf (004010c0)//只有当三个条件都成立才会执行打印操作
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
#include "stdafx.h"


void add()
{
int x=3;
int y=2;
int z=1;
if(x>y||y>z||z==1)
{
printf("OK");
}
}

int main(int argc, char* argv[])
{
add();
return 0;

}


0040B7C8 mov dword ptr [ebp-4],3
0040B7CF mov dword ptr [ebp-8],2
0040B7D6 mov dword ptr [ebp-0Ch],1
0040B7DD mov eax,dword ptr [ebp-4]
0040B7E0 cmp eax,dword ptr [ebp-8]
0040B7E3 jg add+43h (0040b7f3)//第一个参数大于第二个参数直接跳转到printf执行
0040B7E5 mov ecx,dword ptr [ebp-8]
0040B7E8 cmp ecx,dword ptr [ebp-0Ch]
0040B7EB jg add+43h (0040b7f3)//第二个参数大于第三个参数直接跳转到printf执行
0040B7ED cmp dword ptr [ebp-0Ch],1
0040B7F1 jne add+50h (0040b800)//第三个参数如果不等于1就会跳过printf函数
0040B7F3 push offset string "%u\n" (0042001c)
0040B7F8 call printf (004010c0)

单目运算符

++自增

–自减

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
#include "stdafx.h"


void add()
{
int x=0;
int y=0;

printf("%d",++x);//先自增,再参与运算
printf("%d",y++);//先参与运算,再自增

}

int main(int argc, char* argv[])
{
add();
return 0;

}


0040B7C8 mov dword ptr [ebp-4],0
0040B7CF mov dword ptr [ebp-8],0
0040B7D6 mov eax,dword ptr [ebp-4]
0040B7D9 add eax,1//x变量先加一
0040B7DC mov dword ptr [ebp-4],eax
0040B7DF mov ecx,dword ptr [ebp-4]
0040B7E2 push ecx
0040B7E3 push offset string "%d" (0042001c)
0040B7E8 call printf (004010c0)
0040B7ED add esp,8
0040B7F0 mov edx,dword ptr [ebp-8]
0040B7F3 mov dword ptr [ebp-0Ch],edx
0040B7F6 mov eax,dword ptr [ebp-0Ch]
0040B7F9 push eax
0040B7FA push offset string "%d" (0042001c)
0040B7FF mov ecx,dword ptr [ebp-8]
0040B802 add ecx,1//y变量在printf函数参数入栈以后再加一
0040B805 mov dword ptr [ebp-8],ecx
0040B808 call printf (004010c0)

三目运算符

三目运算符和if…else在汇编里的表示形式很像,做逆向没必要区分这二者的区别,只要能把代码写出来就可以,三目运算符只是为了编程方便,没有别的功能

a>b?x:y根据问号前面的公式,成立返回x,不成立返回y

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
#include "stdafx.h"


void add()
{
int x=1;
int y=0;

int z=x>y?x:y;

}

int main(int argc, char* argv[])
{
add();
return 0;

}


0040B7C8 mov dword ptr [ebp-4],1
0040B7CF mov dword ptr [ebp-8],0
0040B7D6 mov eax,dword ptr [ebp-4]
0040B7D9 cmp eax,dword ptr [ebp-8]
0040B7DC jle add+36h (0040b7e6)//如果第一个参数x不大于第二个参数y直接跳到返回第二个值y给第三个值z的地方
0040B7DE mov ecx,dword ptr [ebp-4]
0040B7E1 mov dword ptr [ebp-10h],ecx
0040B7E4 jmp add+3Ch (0040b7ec)//如果第一个参数x大于第二个参数y直接跳到返回第一个值x给第三个值z的地方
0040B7E6 mov edx,dword ptr [ebp-8]
0040B7E9 mov dword ptr [ebp-10h],edx
0040B7EC mov eax,dword ptr [ebp-10h]//eax=(ebp-4)=x
0040B7EF mov dword ptr [ebp-0Ch],eax
0040B7F2 pop edi
0040B7F3 pop esi
0040B7F4 pop ebx
0040B7F5 mov esp,ebp
0040B7F7 pop ebp
0040B7F8 ret