第十二课 c语言5(正向基础)
1.类型转换(movsx,movzx)
小转大
- movsx使用符号位先填上,再把数据传过去
- movzx使用0先填上,再把数据传过去
大转小
高位会丢失
表达式
- 运算中表达式会以最大宽度存放数据
- 当表达式同时存在有符号数和无符号数时,表达式的结构将转换成无符号数
疑点
海哥这里讲乱了,是因为%d是有符号输出,想要输出无符号要用%u
2.循环
- for循环执行顺序
注:循环变量放在里面和外面的区别
作业
尝试运行后解释其运行结果
1、
从ebp-14开始存,到ebp-4是数组最后一个值,越界一个数组将存到ebp,越界两个数组将存到ebp+4,也就是eip的地址
2、
作业2
2、
第十三课 c语言6
1.函数返回值
函数如果有返回值,他在函数内会把结果放在寄存器里面,出了函数后把寄存器里的值传递给变量,根据数据类型编译器自己选择几位寄存器(默认eax寄存器),char类型就选择al,short类型就选择ax,int类型就选择eax
2.函数参数传递
参数传递时到push压栈时还是会使用eax32位去压栈
3.参数与局部变量内存分配
注:这里和数组的内存分配不一样
局部变量分配内存时是都占4个字节不管是charshort或int,但真正使用的时候char还是使用了1个字节
3.数组的本质
一组地址相邻的变量
数组赋值
char arr[10] = {'A','B','C','D','E','F'}; //编译器默认在结尾添加0x00
char arr[3] = {'A','B','C'}; //但是如果没有留出'\0'的空间,编译器就不会自动添加
char arr2[6] = {'A','B','C','D','E',0}; //注意区分这里的0不是'0'
char buffer[100] = ""; //定义了一个空字符串,字符串中每个字节默认初始为0x00
char buffer[] = ""; //这个数组长度只有1,且默认初始为0x00
数组赋值应该在最后加一个\0表示结尾,后面自动填充0,不然输出数组可能会多出一些垃圾数据
4.多维数组
二维数组存储原理
- 二维数组在汇编中的储存和一维数组没有任何区别
二维数组语法
- 给定部分值时
- 多给数值是不允许的
- 以下是允许的
二维数组寻址原理
三维数组
作业
1、分别存在两个寄存器
如果没用__int64就会直接截取
2、数组内存分配
char类型数组和int类型数组内存分配的字节数是不一样的,char类型数组只分一个字节的内存宽度
作业2
问题
答
3、vs优化过了
看老师vc6的
作业3
问题
答
作业4
练习一:
char arr[5][10] ={{1,2,3,4,5,6,7,8,9,10}
{11,12,13,14,15,16,17,18,19,20}
....
{41,42,43,44,45,46,47,48,49,50}}
练习二:
arr[1][5],编译器当作1x10+5,取下标15的值
练习三:
for(int i = 0;i<5;i++)
{
for(int y = 0 ; y<10 ; y++)
{printf(arr[i][y]); }
}
练习四:
for(int i = 0 ; i < 10 ; i++)
{
if(arr[1][i]>20)
{arr[1][i]=21;}
}
练习五:
for (int i = 0; i < 3; i++)
{
for (int y = 0; y < 4; y++)
{
x += arr[i][y];
}
cout << x << endl;
}
作业5:归并排序
问题
答
void a()
{
int arr[8] = { 3,5,7,9,12,25,34,55 };
int add[6] = { 4,7,9,11,13,16 };
int ret[14] = { 0 };
int i = 0;
int y = 0;
int x = 0;
for (; i < 8; i++)
{
for (; y < 6; y++)
{
if (arr[i] < add[y])
{
ret[x] = arr[i];
x++;
break;
}
else if(add[y]<arr[i])
{
ret[x] = add[y];
x++;
}
else
{
ret[x] = add[y];
x++;
y++;
ret[x] = arr[i];
x++;
i++;
break;
}
}
if (y == 6) {
for (; i < 8; i++)
{
ret[x] = arr[i];
x++;
}
}
}
for (int t = 0; t < 14; t++)
{
cout << ret[t] << " " << endl;
}
}
注:循环变量放在里面和外面的区别
第十四课 c语言7结构体
结构体1
优势:结构体可以定义多种类型,本质就是把一堆不同类型的东西定义打包在一起
定义时不会分配空间,只有在使用的时候才会分配空间
结构体初始化
定义了两个结构体,最下面定义了一个类型为Mon的变量gsl,这是一个结构体数组,每个gsl[0]变量都有一些空间可以去定义,比如gsl[0].name[0],或者gsl[0].blood。
错误示范
结构体和数组区分
- 内存地址等宽为数组,不等宽可以看作结构体,虽然也有等宽的结构体,但是我们一样可以当作数组看待,有时候逆向也没办法把所有代码都准确逆向出来
- 结构体和数组都得看是定义在全局还是局部,来判断是直接分配内存还是在堆栈里
- 且结构体的内存分配和局部变量不一样,局部变量都按本机宽度分配,结构体按类型分配
结构体大时如何把参数传入函数
相当于栈顶开辟一块空间把参数都复制进去
结构体2
1.数据对齐
结构体存放顺序不一样,内存空间大小不一样
对齐规则
#pragma pack
当定义了字节对齐数,在结构体中由最小那个字节对齐,比如#pragma pack(4),char类型还是以1字节对齐,但是__int64就是以4字节对齐,因为__int64和4相比是4小,所以以4为准。
建议:
所以建议结构体从小到大存储