发表于 2020-9-9 21:21:47
|
查看: 10334
|
回复: 2
目录 代码还原反汇编之除法除数为非2的幂 系列文章 一丶数学知识补充 1.1 简介 1.2 分数 1.2.1分数加法 1.2.1分数乘法 二丶除法优化之有符号非2的幂优化 2.1高级代码与反汇编 2.2 除法非2的幂还原 2.3 除数为非2的幂的优化与原理 2.4 总结除法还原公式 三丶除法优化之无符号非2的幂优化 3.1 无符号非2的幂除数为正代码反汇编还原 3.2 无符号非2的幂除数为负数反汇编代码还原 3.3 特殊汇编 四丶为什么学习除法优化 4.1 为什么学习除法优化 五丶高级Vs编译器与linux下的gcc优化 5.1 vs2019 x86 有符号非2的幂优化 5.2 vs2019 x64有符号非2的幂优化 5.3 linux gcc x86 有符号非2的幂 5.4 其它同理自己建立项目研究
代码还原反汇编之除法除数为非2的幂 系列文章 反汇编技术之熟悉IDA工具
反汇编逆向技术之寻找Main入口点
反汇编代码还原之优化方式
反汇编代码还原之加减乘
反汇编代码还原之除法为2的幂
一丶数学知识补充 1.1 简介 除法在非2的幂优化上,采用的是除法转变为乘法 的形式. 在学习这方面知识的时候我们先了解下简单的数学知识
也有助于我们能看懂公式
1.2 分数 1.2.1分数加法 分数加法
相同分母加法 分子想加 分母不变 例如下
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
不同分母想加 如果是不同分母想加你就要进行寻找最小公分母
公分母指的是. 当两个或者以上的分数有相同 的分母 那么他们便是公分母 注意这里是公分母 .而不是最小公分母 最小公分母指的是两个分数以上,最小的公分母
最小公分母的寻找
最小公分母我们可以列出 分母的倍数 如果有两个分数那么都列出分母的倍数.找出相同的倍数.然后让其等价即可.
例如:
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
列出3的倍数: 3 6 9 12 15 .....
列出6的倍数: 6 12 18 24 ....
我们发现最小公倍数都是6. 所以我们的分子分母都*2转为为相同分母然后进行想加即可
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
1.2.1分数乘法 分数乘法
**分数*分数 是分子 * 分子 分母 * 分母**
如下:
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
口诀: 乘分数 没难度 上乘上 下乘下 再约分
整数相乘
如果一个整数 * 一个分数.那么这个分数就可以看做是分子,而分母就是1
例子:
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
至于约分.可以寻找最小公因数.跟公倍数相反.公倍数是找出相乘 公因数就是找出可以分子/分母的数. 都去除同一个数
二丶除法优化之有符号非2的幂优化 2.1高级代码与反汇编 int main(int argc, char* argv[]) {
/*
除法
*/
int NumberOne = 0;
int NumberTwo = 0;
scanf("%d",&NumberOne);
scanf("%d",&NumberTwo);
int Count1 = NumberOne / 3;
int Count2 = NumberTwo / 5;
int Count3 = NumberTwo / 6;
int Count4 = NumberTwo / 9;
printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
system("pause");
return 0;
}
汇编对应代码
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp) .text:00401000 _main proc near ; CODE XREF: start+AF↓p
.text:00401000
.text:00401000 var_8 = dword ptr -8
.text:00401000 var_4 = dword ptr -4
.text:00401000 argc = dword ptr 4
.text:00401000 argv = dword ptr 8
.text:00401000 envp = dword ptr 0Ch
.text:00401000
.text:00401000 sub esp, 8
.text:00401003 xor eax, eax
.text:00401005 mov [esp+8+var_8], eax
.text:00401009 mov [esp+8+var_4], eax
.text:0040100D lea eax, [esp+8+var_8]
.text:00401011 push eax
.text:00401012 push offset aD ; "%d"
.text:00401017 call _scanf
.text:0040101C lea ecx, [esp+10h+var_4]
.text:00401020 push ecx
.text:00401021 push offset aD ; "%d"
.text:00401026 call _scanf
//第一段
.text:0040102B mov ecx, [esp+18h+var_8]
.text:0040102F mov eax, 55555556h
.text:00401034 imul ecx
.text:0040103A mov eax, edx
.text:0040103C shr eax, 1Fh
.text:0040103F add edx, eax
//第二段
.text:00401036 mov ecx, [esp+18h+var_4]
.text:00401041 mov eax, 66666667h
.text:00401047 imul ecx
.text:00401049 sar edx, 1
.text:0040104B mov eax, edx
.text:0040104D shr eax, 1Fh
.text:00401050 add edx, eax
.text:00401057 push edx //这里原先是流水线优化给提到上边来了
//第三段
.text:00401052 mov eax, 2AAAAAABh
.text:00401058 imul ecx
.text:0040105A mov eax, edx
.text:0040105C shr eax, 1Fh
.text:0040105F add edx, eax
.text:00401066 push edx //同上流水线优化
//第四段
.text:00401061 mov eax, 38E38E39h
.text:00401067 imul ecx
.text:00401069 sar edx, 1
.text:0040106B mov ecx, edx
.text:0040106D shr ecx, 1Fh
.text:00401070 add edx, ecx
.text:00401072 push edx
.text:00401073 push offset aDDDDD ; "%d%d%d%d%d"
.text:00401078 call _printf
.text:0040107D push offset aPause ; "pause"
.text:00401082 call _system
.text:00401087 xor eax, eax
.text:00401089 add esp, 30h
.text:0040108C retn
.text:0040108C _main endp
2.2 除法非2的幂还原 乍一看上面汇编代码.除法怎么变为了这样.为什么又有乘法又有除法.还有调整等. 那么这里就着重讲解一下.
如果想要直接还原.那么我们把代码定式提取出来 直接进行还原
代码定式
mov ecx, 被除数 mov eax, M值
imul ecx
sar edx, n
mov eax, edx
shr eax, 1Fh
add edx, eax
push edx
根据汇编我们只需要看三个点即可. 并且得出三个点的公式得原理
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
其中M是编译器计算出来了. ecx是被除数. 这里sar n值.直接操作的是edx. 这里其实是除法转变为了乘法 而如果除法转变为乘法 那么在32位年代下.两个数相乘 32的值是不会放下的. 所以我们这里其实使用的是 edx,eax 来代表乘法的结果 然后我们直接操作了乘积的高位 这里右移1 等价于是 除以
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
那么我们还原的时候直接记住死公式就可以.
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
直接统计n的取值. 然后用 2的32次方 + n即可. 因为乘积的低位时代表2^32次方.这里直接是对乘积高位做操作.所以我们需要加上低位的32次方的值
例子还原
.text:0040102B mov ecx, [esp+18h+var_8] .text:0040102F mov eax, 55555556h
.text:00401034 imul ecx
.text:0040103A mov eax, edx //这里直接使用的是edx.而没有对edx做修改.所以我们的n值就是0
.text:0040103C shr eax, 1Fh
.text:0040103F add edx, eax
我们套用公式
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
2.99直接向上取整 = 3. 所以这里我们就寻得被除数为3
2.3 除数为非2的幂的优化与原理 首先先看我们的汇编
.text:00401061 mov eax, 38E38E39h .text:00401067 imul ecx
.text:00401069 sar edx, 1
.text:0040106B mov ecx, edx
.text:0040106D shr ecx, 1Fh
.text:00401070 add edx, ecx
.text:00401072 push edx
这里我们汇编分为两部分.上边是可以直接套用公式还原. 而下方其实是获取符号位.调整一下符号位.
shr 逻辑右移. 最高位以0填充. 右移31(1F)位 取得符号位 然后这里有一个加法.其实这个加法也是套路.跟我们之前讲解的无分支优化差不多. 如果结果是正数. 那么 add edx,eax 就是加0 等于什么都不干. 如果是结果是负数 那么我们就需要除法的商做调整.做加1调整.
除法转化为乘法的原理
如果想要了解为什么非2的幂代码会变成上面的代码.那么我们就要理解下原理
设 a = 被除数 b = 除数(是一个常量值)
那么就会有以下公式
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
这个就是我们上面所了解的分数相关知识.
看最后的公式
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
其中 2n/b这个是可以在编译期中计算出来的. VC++6.0 或者VS2019 在编译 期间n的取值是大于32的.所以是可以算出来的.
所以我们的公式可以变为如下 在这里我们把编译器可以计算出来的值记做C. 那么可以得出以下公式
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
最终简化为就是(a * c) >> n 而反过头来看我们的汇编代码
.text:00401061 mov eax, 38E38E39h .text:00401067 imul ecx
.text:00401069 sar edx, 1
列出公式
ecx = 被除数
eax = M 等价于 2n/b的值.
ecx eax / 2^33 这条公式就正好对应着我们除法转变为乘法的原理 和我们上面的公式一样. (a c) >> n
所以我们解方程即可. 2^n / b = M 值. 那么 2^n / M = b b就是我们的要求的除数. 所以得出我们的除数
除法还原公式为:
2.4 总结除法还原公式 除法的还原公式
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
这里的C其实就是2^n/b 在汇编中我们也设为M.所以也可以写为如下
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
除法转变为乘法的公式
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
转变为如下
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
继续转变
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
最终转变
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
对于上面我们记住代码定式也可以进行还原.当然熟悉除法转变为乘法的原理更好.
高级代码看其特征我们发现其实是一样的. 都可以使用 除法转乘法的公式来进行还原
除法还原公式其实就是解方程了.解开就可以得到被除数
三丶除法优化之无符号非2的幂优化 高级代码
int main(int argc, char* argv[]) {
/*
除法
*/
unsigned int NumberOne = 0;
unsigned int NumberTwo = 0;
scanf("%u",&NumberOne);
scanf("%u",&NumberTwo);
unsigned int Count1 = NumberOne / 3;
unsigned int Count2 = NumberTwo / 5;
unsigned int Count3 = NumberTwo / 6;
unsigned int Count4 = NumberTwo / 9;
printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
system("pause");
return 0;
}
汇编代码
.text:00401005 mov [esp+8+var_8], eax .text:00401009 mov [esp+8+var_4], eax
.text:0040102B mov eax, 2863311531
.text:00401030 mov ecx, [esp+18h+var_4]
.text:00401034 mul [esp+18h+var_8]
.text:00401038 shr edx, 1
.text:0040103A mov eax, 3435973837
.text:0040103F push edx
.text:00401040 mul ecx
.text:00401042 shr edx, 2
.text:00401045 mov eax, 0AAAAAAABh
.text:0040104A push edx
.text:0040104B mul ecx
.text:0040104D shr edx, 2
.text:00401050 mov eax, 38E38E39h
.text:00401055 push edx
.text:00401056 mul ecx
.text:00401058 shr edx, 1
.text:0040105A push edx
3.1 无符号非2的幂除数为正代码反汇编还原 看如上代码.根据除法转为乘法公式 (a * b) >> n .我们可以求出
2^n / b = M 2^n/M = b (除数常量)
这里只不过是换成了无符号而已.
还原公式还是同上
如:
.text:0040102B mov eax, 2863311531 .text:00401030 mov ecx, [esp+18h+var_4]
.text:00401034 mul [esp+18h+var_8]
.text:00401038 shr edx, 1
取N 值 = 1 取M值 = 2863311531(注意这里IDA我按了下H转为10进制来查看.这样方便我们用科学计算器来进行运算)
操作的是edx.所以
被除数 = 2^33 除数 = M
求除数公式 = 2^n/M = b
代入公式
2^33 / 2863311531 = 2.999999999 向上取整 = 3 所以得出这里的除数为3. ecx = var4
所以这里反汇编为高级代码为 var_4 / 3
3.2 无符号非2的幂除数为负数反汇编代码还原 高级代码如下
int main(int argc, char* argv[]) {
/*
除法
*/
unsigned int NumberOne = 0;
unsigned int NumberTwo = 0;
scanf("%u",&NumberOne);
scanf("%u",&NumberTwo);
unsigned int Count1 = NumberOne / -3;
unsigned int Count2 = NumberTwo / -5;
unsigned int Count3 = NumberTwo / -6;
unsigned int Count4 = NumberTwo / -9;
printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
system("pause");
return 0;
}
核心代码反汇编 代码段
.text:00401005 mov [esp+8+var_8], eax .text:00401009 mov [esp+8+var_4], eax
/-3
.text:0040102B mov eax, 40000001h
.text:00401030 mov ecx, [esp+18h+var_4]
.text:00401034 mul [esp+18h+var_8]
.text:00401038 shr edx, 1Eh
.text:00401040 push edx
/-5
.text:0040103B mov eax, 80000003h
.text:00401041 mul ecx
.text:00401043 shr edx, 1Fh
.text:0040104B push edx
/-6
.text:00401046 mov eax, 7
.text:0040104C mul ecx
.text:0040104E mov eax, ecx
.text:00401050 sub eax, edx
.text:00401052 shr eax, 1
.text:00401054 add eax, edx
.text:00401056 shr eax, 1Fh
.text:00401059 push eax
/-9
.text:0040105A mov eax, 80000005h
.text:0040105F mul ecx
.text:00401061 shr edx, 1Fh
.text:00401064 push edx
代码定式
根据上面反汇编代码.我们看到三个地方 有我们的 疑似 (a * c) >> n 的代码
也就是除法转变为乘法的公式
我们随便取出一处代入公式进行还原
设 M = 40000001h =10进制的 1073741825
设 n = 1E = 10进制的 30
那么代入我们的还原公式为:
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
以计算器的科学计算计算出的数值是4294967292(10进制)
那么我们将这个数复制到以程序员计算的计算器中.(复制到Dec 10进制输入) 可以看到是一个负数
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
注意输入的时候以QWORD输入.然后再点击一下变成DWORD则可以看到表达为-4
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
此时直接对其NOT取反则可以得到原始的被除数. 但是这个被除数常量是负数
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
你也可以让此值做+1调整 变为4294967293 那么就得出了数直接就是-3 可以很明确的知道我们的被除数是-3
3.3 特殊汇编 看到上面有一段代码.我们特别不理解 为什么/-6汇编变了
这些后面有专题转么讲解特殊的怎么还原
现在可以看一下我算的
2^64 / 4,294,967,302 = 0x100000006 最高位为符号位 代表这是个负数也就是-6
如果根据定式还原得出的结果为 0xFFFFFFF9 然后对其取反得到6
但是也有代码定式
mov regA,[ebp - xxx] mov reg,M
mul regA
sub regA,edx
shr regA,n
add regA,edx
shr regA,(n-1)
观看代码定式可以得出
乘减移加移
这种先使用定式还原
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
这里取出两个n值. 1+31 = 32所以n值为32
代入公式得
2^64 / 4,294,967,303 = 0XFFFFFFF9
关于特殊汇编在下一篇应该会详细讲解.
四丶为什么学习除法优化 4.1 为什么学习除法优化 还是那句话为什么学习除法优化. 好就以我们上面的例子为例.那么使用IDA F5查看
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
请问看到这种代码你怕了吗. 直接反汇编可以得出这一段代码我是干啥.用IDA反汇编就会得出 右移等等.在我们看来就是硬汇编
也就是硬着头皮还原的.所以说这就是我们学习的意义所在 当然F5还是很强大的.但是我们学会了能更好的帮助我们进行反汇编,更好的通过反汇编从而还原为高级代码
五丶高级Vs编译器与linux下的gcc优化 其实还是老生常谈.拿高版本与低版本做个对比.看看优化方式是否发生了改变.
5.1 vs2019 x86 有符号非2的幂优化 高级代码
int main(int argc, char* argv[]) {
/*
除法
*/
int NumberOne = 0;
int NumberTwo = 0;
scanf("%d",&NumberOne);
scanf("%d",&NumberTwo);
int Count1 = NumberOne / 3;
int Count2 = NumberTwo / 5;
int Count3 = NumberTwo / 6;
int Count4 = NumberTwo / 9;
printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
system("pause");
return 0;
}
汇编
.text:00401080 push ebp .text:00401081 mov ebp, esp
.text:00401083 sub esp, 8
.text:00401086 lea eax, [ebp+var_4]
.text:00401089 mov [ebp+var_4], 0
.text:00401090 push eax
.text:00401091 push offset unk_41ECDC
.text:00401096 mov [ebp+var_8], 0
.text:0040109D call sub_401050
.text:004010A2 lea eax, [ebp+var_8]
.text:004010A5 push eax
.text:004010A6 push offset unk_41ECDC
.text:004010AB call sub_401050
.text:004010B0 mov ecx, [ebp+var_8]
.text:004010B3 mov eax, 55555556h
.text:004010B8 imul [ebp+var_4]
.text:004010BB mov eax, edx
.text:004010BD shr eax, 1Fh
.text:004010C0 add eax, edx
.text:004010C2 push eax
.text:004010C3 mov eax, 66666667h
.text:004010C8 imul ecx
.text:004010CA sar edx, 1
.text:004010CC mov eax, edx
.text:004010CE shr eax, 1Fh
.text:004010D1 add eax, edx
.text:004010D3 push eax
.text:004010D4 mov eax, 2AAAAAABh
.text:004010D9 imul ecx
.text:004010DB mov eax, edx
.text:004010DD shr eax, 1Fh
.text:004010E0 add eax, edx
.text:004010E2 push eax
.text:004010E3 mov eax, 38E38E39h
.text:004010E8 imul ecx
.text:004010EA sar edx, 1
.text:004010EC mov eax, edx
.text:004010EE shr eax, 1Fh
.text:004010F1 add eax, edx
.text:004010F3 push eax
.text:004010F4 push offset aDDDDD ; "%d%d%d%d%d"
.text:004010F9 call sub_401020
.text:004010FE push offset aPause ; "pause"
.text:00401103 call sub_4048E7
.text:00401108 add esp, 28h
.text:0040110B xor eax, eax
.text:0040110D mov esp, ebp
.text:0040110F pop ebp
这里流水线优化等也不去掉了.可以发现跟VC6.0无任何区别
5.2 vs2019 x64有符号非2的幂优化 高级代码
int main(int argc, char* argv[]) {
/*
除法
*/
__int64 NumberOne = 0;
__int64 NumberTwo = 0;
scanf("%I64d", &NumberOne);
scanf("%I64d", &NumberTwo);
__int64 Count1 = NumberOne / 3;
__int64 Count2 = NumberTwo / 5;
__int64 Count3 = NumberTwo / 6;
__int64 Count4 = NumberTwo / 9;
printf("%I64d%I64d%lld%lld", Count4, Count3, Count2, Count1);
system("pause");
return 0;
}
反汇编
text:00000001400010D0 sub rsp, 38h .text:00000001400010D4 xor eax, eax
.text:00000001400010D6 lea rdx, [rsp+38h+arg_10]
.text:00000001400010DB lea rcx, aI64d ; "%I64d"
.text:00000001400010E2 mov [rsp+38h+arg_10], rax
.text:00000001400010E7 mov [rsp+38h+arg_18], rax
.text:00000001400010EC call sub_140001080
.text:00000001400010F1 lea rdx, [rsp+38h+arg_18]
.text:00000001400010F6 lea rcx, aI64d ; "%I64d"
.text:00000001400010FD call sub_140001080
.text:0000000140001102 mov rcx, [rsp+38h+arg_18]
.text:0000000140001107 mov rax, 5555555555555556h
.text:0000000140001111 imul [rsp+38h+arg_10]
.text:0000000140001116 mov rax, 6666666666666667h
.text:0000000140001120 mov r10, rdx
.text:0000000140001123 shr r10, 3Fh
.text:0000000140001127 add r10, rdx
.text:000000014000112A imul rcx
.text:000000014000112D mov [rsp+38h+var_18], r10
.text:0000000140001132 mov r9, rdx
.text:0000000140001135 sar r9, 1
.text:0000000140001138 mov rax, r9
.text:000000014000113B shr rax, 3Fh
.text:000000014000113F add r9, rax
.text:0000000140001142 mov rax, 2AAAAAAAAAAAAAABh
.text:000000014000114C imul rcx
.text:000000014000114F mov rax, 1C71C71C71C71C72h
.text:0000000140001159 mov r8, rdx
.text:000000014000115C shr r8, 3Fh
.text:0000000140001160 add r8, rdx
.text:0000000140001163 imul rcx
.text:0000000140001166 lea rcx, aI64dI64dLldLld ; "%I64d%I64d%lld%lld"
.text:000000014000116D mov rax, rdx
.text:0000000140001170 shr rax, 3Fh
.text:0000000140001174 add rdx, rax
.text:0000000140001177 call sub_140001020
.text:000000014000117C lea rcx, aPause ; "pause"
.text:0000000140001183 call sub_1400045C4
.text:0000000140001188 xor eax, eax
.text:000000014000118A add rsp, 38h
.text:000000014000118E retn
观看反汇编其实跟x86一致
这里还是去掉流水线优化 提取核心代码位置进行反汇编
.text:0000000140001107 mov rax, 5555555555555556h .text:0000000140001111 imul [rsp+38h+arg_10]
.text:0000000140001120 mov r10, rdx
.text:0000000140001123 shr r10, 3Fh
.text:0000000140001127 add r10, rdx
M数值变大.还是代入公式即可. 这里使用的mov r10,rdx 说明直接使用的rdx. rdx是一个64位数. 所以 2^64 / M = 2.9999999 向上取整 = 3
5.3 linux gcc x86 有符号非2的幂 高级代码
#include<stdio.h> int main()
{
int NumberOne = 0;
int NumberTwo = 0;
scanf("%d", &NumberOne);
scanf("%d", &NumberTwo);
int Count1 = NumberOne / 3;
int Count2 = NumberTwo / 5;
int Count3 = NumberTwo / 6;
int Count4 = NumberTwo / 9;
printf("%d%d%d%d", Count4, Count3, Count2, Count1);
scanf("%d", &Count4);
scanf("%d", &Count3);
scanf("%d", &Count2);
scanf("%d", &Count1);
printf("%d%d%d%d", Count4, Count3, Count2, Count1);
return 0;
}
如果你是64位系统.那么你使用gcc命令如下
编译出来即可. 其实下面反汇编跟x86 vc++6.0 vs2019 一样.可以不用看了.
反汇编
.text:080484BB ; int __cdecl main(int argc, const char **argv, const char **envp) .text:080484BB public main
.text:080484BB main proc near ; DATA XREF: _start+17↑o
.text:080484BB
.text:080484BB var_24 = dword ptr -24h
.text:080484BB var_20 = dword ptr -20h
.text:080484BB var_1C = dword ptr -1Ch
.text:080484BB var_18 = dword ptr -18h
.text:080484BB var_14 = dword ptr -14h
.text:080484BB var_10 = dword ptr -10h
.text:080484BB var_C = dword ptr -0Ch
.text:080484BB argc = dword ptr 8
.text:080484BB argv = dword ptr 0Ch
.text:080484BB envp = dword ptr 10h
.text:080484BB
.text:080484BB ; __unwind {
.text:080484BB lea ecx, [esp+4]
.text:080484BF and esp, 0FFFFFFF0h
.text:080484C2 push dword ptr [ecx-4]
.text:080484C5 push ebp
.text:080484C6 mov ebp, esp
.text:080484C8 push ebx
.text:080484C9 push ecx
.text:080484CA sub esp, 20h
.text:080484CD mov eax, large gs:14h
.text:080484D3 mov [ebp+var_C], eax
.text:080484D6 xor eax, eax
.text:080484D8 mov [ebp+var_24], 0
.text:080484DF mov [ebp+var_20], 0
.text:080484E6 sub esp, 8
.text:080484E9 lea eax, [ebp+var_24]
.text:080484EC push eax
.text:080484ED push offset unk_80486B0
.text:080484F2 call ___isoc99_scanf
.text:080484F7 add esp, 10h
.text:080484FA sub esp, 8
.text:080484FD lea eax, [ebp+var_20]
.text:08048500 push eax
.text:08048501 push offset unk_80486B0
.text:08048506 call ___isoc99_scanf
.text:0804850B add esp, 10h
.text:0804850E mov ecx, [ebp+var_24]
.text:08048511 mov edx, 55555556h
.text:08048516 mov eax, ecx
.text:08048518 imul edx
.text:0804851A mov eax, ecx
.text:0804851C sar eax, 1Fh
.text:0804851F sub edx, eax
.text:08048521 mov eax, edx
.text:08048523 mov [ebp+var_1C], eax
.text:08048526 mov ecx, [ebp+var_20]
.text:08048529 mov edx, 66666667h
.text:0804852E mov eax, ecx
.text:08048530 imul edx
.text:08048532 sar edx, 1
.text:08048534 mov eax, ecx
.text:08048536 sar eax, 1Fh
.text:08048539 sub edx, eax
.text:0804853B mov eax, edx
.text:0804853D mov [ebp+var_18], eax
.text:08048540 mov ecx, [ebp+var_20]
.text:08048543 mov edx, 2AAAAAABh
.text:08048548 mov eax, ecx
.text:0804854A imul edx
.text:0804854C mov eax, ecx
.text:0804854E sar eax, 1Fh
.text:08048551 sub edx, eax
.text:08048553 mov eax, edx
.text:08048555 mov [ebp+var_14], eax
.text:08048558 mov ecx, [ebp+var_20]
.text:0804855B mov edx, 38E38E39h
.text:08048560 mov eax, ecx
.text:08048562 imul edx
.text:08048564 sar edx, 1
.text:08048566 mov eax, ecx
.text:08048568 sar eax, 1Fh
.text:0804856B sub edx, eax
.text:0804856D mov eax, edx
5.4 其它同理自己建立项目研究 自己建立项目研究.高手复习 新手学习 谢谢观看
温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【
投诉建议 】板块发帖举报。