算术操作符 自增运算符 逆向汇编三
文章目录
- 自增运算符
- 代码
- 汇编代码
- 汇编分析
- **汇编代码分析(自增/自减运算符)**
- **1. 后置自增(`i++`)**
- **C 代码**
- **汇编代码**
- **2. 前置自增(`++i`)**
- **C 代码**
- **汇编代码**
- **3. 后置自减(`i--`)**
- **C 代码**
- **汇编代码**
- **4. 前置自减(`--i`)**
- **C 代码**
- **汇编代码**
- **5. 复杂表达式中的自增/自减**
- **C 代码**
- **汇编代码**
- **(1) `a++ * 2`**
- **(2) `++b * 2`**
- **(3) `c-- + 5`**
- **(4) `--d + 5`**
- **6. 数组索引中的应用**
- **C 代码**
- **汇编代码**
- **(1) `arr[index++]`**
- **(2) `arr[++index]`**
- **7. 未定义行为(`i++ + ++i`)**
- **C 代码**
- **汇编代码**
- **(1) `i++`**
- **(2) `++i`**
- **(3) `part1 + part2`**
- **8. 多个变量混合示例**
- **C 代码**
- **汇编代码**
- **(1) `x++ + y++`**
- **(2) `++x + ++y`**
- **关键结论**
- **总结**
自增运算符
代码
#include <stdio.h>int main() {// 1. 后置自增 (i++){int i = 5;int result = i++; // 先使用i的当前值5赋值给result,然后i自增为6// 此时:result = 5, i = 6}// 2. 前置自增 (++i){int i = 5;int result = ++i; // 先将i自增为6,然后使用新值6赋值给result// 此时:result = 6, i = 6}// 3. 后置自减 (i--){int i = 5;int result = i--; // 先使用i的当前值5赋值给result,然后i自减为4// 此时:result = 5, i = 4}// 4. 前置自减 (--i){int i = 5;int result = --i; // 先将i自减为4,然后使用新值4赋值给result// 此时:result = 4, i = 4}// 5. 在复杂表达式中的使用{int a = 3, b = 3, c = 3, d = 3;int result1 = a++ * 2; // 先计算 3*2=6,然后a自增为4int result2 = ++b * 2; // 先b自增为4,然后计算 4*2=8int result3 = c-- + 5; // 先计算 3+5=8,然后c自减为2int result4 = --d + 5; // 先d自减为2,然后计算 2+5=7}// 6. 数组索引中的应用{int arr[] = { 10, 20, 30, 40 };int index = 0;int val1 = arr[index++]; // 先取arr[0]=10,然后index自增为1int val2 = arr[++index]; // 先index自增为2,然后取arr[2]=30}// 7. 应避免的未定义行为示例{int i = 5;// 未定义行为 - 在同一个表达式中对同一变量多次自增// int bad_example = i++ + ++i; // 不要这样做!// 正确的做法 - 分开写int part1 = i++; // i=5, part1=5, 然后i=6int part2 = ++i; // i=6, 先自增为7, part2=7int correct_result = part1 + part2; // 5+7=12}// 8. 多个变量混合示例{int x = 1, y = 1;int a = x++ + y++; // a = 1+1=2, 然后x=2, y=2int b = ++x + ++y; // 先x=3, y=3, 然后b=3+3=6}return 0;
}
汇编代码
int main() {
004153A0 push ebp
004153A1 mov ebp,esp
004153A3 sub esp,21Ch
004153A9 push ebx
004153AA push esi
004153AB push edi
004153AC lea edi,[ebp-15Ch]
004153B2 mov ecx,57h
004153B7 mov eax,0CCCCCCCCh
004153BC rep stos dword ptr es:[edi]
004153BE mov ecx,offset _C66D3399_simple_cpp@cpp (041C008h)
004153C3 call @__CheckForDebuggerJustMyCode@4 (041131Bh)
004153C8 nop // 1. 后置自增 (i++){int i = 5;
004153C9 mov dword ptr [ebp-8],5 int result = i++; // 先使用i的当前值5赋值给result,然后i自增为6
004153D0 mov eax,dword ptr [ebp-8]
004153D3 mov dword ptr [ebp-14h],eax
004153D6 mov ecx,dword ptr [ebp-8]
004153D9 add ecx,1
004153DC mov dword ptr [ebp-8],ecx // 此时:result = 5, i = 6}// 2. 前置自增 (++i){int i = 5;
004153DF mov dword ptr [ebp-20h],5 int result = ++i; // 先将i自增为6,然后使用新值6赋值给result
004153E6 mov eax,dword ptr [ebp-20h]
004153E9 add eax,1
004153EC mov dword ptr [ebp-20h],eax
004153EF mov ecx,dword ptr [ebp-20h]
004153F2 mov dword ptr [ebp-2Ch],ecx // 此时:result = 6, i = 6}// 3. 后置自减 (i--){int i = 5;
004153F5 mov dword ptr [ebp-38h],5 int result = i--; // 先使用i的当前值5赋值给result,然后i自减为4
004153FC mov eax,dword ptr [ebp-38h]
004153FF mov dword ptr [ebp-44h],eax
00415402 mov ecx,dword ptr [ebp-38h]
00415405 sub ecx,1
00415408 mov dword ptr [ebp-38h],ecx // 此时:result = 5, i = 4}// 4. 前置自减 (--i){int i = 5;
0041540B mov dword ptr [ebp-50h],5 int result = --i; // 先将i自减为4,然后使用新值4赋值给result
00415412 mov eax,dword ptr [ebp-50h]
00415415 sub eax,1
00415418 mov dword ptr [ebp-50h],eax
0041541B mov ecx,dword ptr [ebp-50h]
0041541E mov dword ptr [ebp-5Ch],ecx // 此时:result = 4, i = 4}// 5. 在复杂表达式中的使用{int a = 3, b = 3, c = 3, d = 3;
00415421 mov dword ptr [ebp-68h],3
00415428 mov dword ptr [ebp-74h],3
0041542F mov dword ptr [ebp-80h],3
00415436 mov dword ptr [ebp-8Ch],3 int result1 = a++ * 2; // 先计算 3*2=6,然后a自增为4
00415440 mov eax,dword ptr [ebp-68h]
00415443 shl eax,1
00415445 mov dword ptr [ebp-98h],eax
0041544B mov ecx,dword ptr [ebp-68h]
0041544E add ecx,1
00415451 mov dword ptr [ebp-68h],ecx int result2 = ++b * 2; // 先b自增为4,然后计算 4*2=8
00415454 mov eax,dword ptr [ebp-74h]
00415457 add eax,1
0041545A mov dword ptr [ebp-74h],eax
0041545D mov ecx,dword ptr [ebp-74h]
00415460 shl ecx,1
00415462 mov dword ptr [ebp-0A4h],ecx int result3 = c-- + 5; // 先计算 3+5=8,然后c自减为2
00415468 mov eax,dword ptr [ebp-80h]
0041546B add eax,5
0041546E mov dword ptr [ebp-0B0h],eax
00415474 mov ecx,dword ptr [ebp-80h]
00415477 sub ecx,1
0041547A mov dword ptr [ebp-80h],ecx int result4 = --d + 5; // 先d自减为2,然后计算 2+5=7
0041547D mov eax,dword ptr [ebp-8Ch]
00415483 sub eax,1
00415486 mov dword ptr [ebp-8Ch],eax
0041548C mov ecx,dword ptr [ebp-8Ch]
00415492 ?? ??????
00415493 ?? ??????
00415494 ?? ??????
00415495 ?? ??????
00415496 ?? ??????
00415497 ?? ??????
00415498 ?? ??????
00415499 ?? ??????
0041549A ?? ??????
0041549B ?? ??????
0041549C ?? ??????
0041549D ?? ??????
0041549E ?? ??????
0041549F ?? ??????
004154A0 ?? ??????
004154A1 ?? ??????
004154A2 ?? ??????
004154A3 ?? ??????
004154A4 ?? ??????
004154A5 ?? ??????
004154A6 ?? ??????
004154A7 ?? ??????
004154A8 ?? ??????
004154A9 ?? ??????
--- C:\Code\Cpp\simple_cpp\simple_cpp.cpp --------------------------------------}// 6. 数组索引中的应用{int arr[] = { 10, 20, 30, 40 };
004154AA call dword ptr [eax+eax]
004154AD add byte ptr [eax],al
004154AF mov dword ptr [ebp-0CCh],1Eh
004154B9 mov dword ptr [ebp-0C8h],28h int index = 0;
004154C3 mov dword ptr [ebp-0E0h],0 int val1 = arr[index++]; // 先取arr[0]=10,然后index自增为1
004154CD mov eax,dword ptr [ebp-0E0h]
004154D3 mov ecx,dword ptr [ebp+eax*4-0D4h]
004154DA mov dword ptr [ebp-0ECh],ecx
004154E0 mov edx,dword ptr [ebp-0E0h]
004154E6 add edx,1
004154E9 mov dword ptr [ebp-0E0h],edx int val2 = arr[++index]; // 先index自增为2,然后取arr[2]=30
004154EF mov eax,dword ptr [ebp-0E0h]
004154F5 add eax,1
004154F8 mov dword ptr [ebp-0E0h],eax
004154FE mov ecx,dword ptr [ebp-0E0h]
00415504 mov edx,dword ptr [ebp+ecx*4-0D4h]
0041550B mov dword ptr [ebp-0F8h],edx }// 7. 应避免的未定义行为示例{int i = 5;
00415511 mov dword ptr [ebp-104h],5 // 未定义行为 - 在同一个表达式中对同一变量多次自增// int bad_example = i++ + ++i; // 不要这样做!// 正确的做法 - 分开写int part1 = i++; // i=5, part1=5, 然后i=6
0041551B mov eax,dword ptr [ebp-104h]
00415521 mov dword ptr [ebp-110h],eax
00415527 mov ecx,dword ptr [ebp-104h]
0041552D add ecx,1
00415530 mov dword ptr [ebp-104h],ecx int part2 = ++i; // i=6, 先自增为7, part2=7
00415536 mov eax,dword ptr [ebp-104h]
0041553C add eax,1
0041553F mov dword ptr [ebp-104h],eax
00415545 mov ecx,dword ptr [ebp-104h]
0041554B mov dword ptr [ebp-11Ch],ecx int correct_result = part1 + part2; // 5+7=12
00415551 mov eax,dword ptr [ebp-110h]
00415557 add eax,dword ptr [ebp-11Ch]
0041555D mov dword ptr [ebp-128h],eax }// 8. 多个变量混合示例{int x = 1, y = 1;
00415563 mov dword ptr [ebp-134h],1
0041556D mov dword ptr [ebp-140h],1 int a = x++ + y++; // a = 1+1=2, 然后x=2, y=2
00415577 mov eax,dword ptr [ebp-134h]
0041557D add eax,dword ptr [ebp-140h]
00415583 mov dword ptr [ebp-14Ch],eax
00415589 mov ecx,dword ptr [ebp-140h]
0041558F add ecx,1
00415592 mov dword ptr [ebp-140h],ecx
00415598 mov edx,dword ptr [ebp-134h]
0041559E add edx,1
004155A1 mov dword ptr [ebp-134h],edx int b = ++x + ++y; // 先x=3, y=3, 然后b=3+3=6
004155A7 mov eax,dword ptr [ebp-134h]
004155AD add eax,1
004155B0 mov dword ptr [ebp-134h],eax
004155B6 mov ecx,dword ptr [ebp-140h]
004155BC add ecx,1
004155BF mov dword ptr [ebp-140h],ecx
004155C5 mov edx,dword ptr [ebp-134h]
004155CB add edx,dword ptr [ebp-140h]
004155D1 mov dword ptr [ebp-158h],edx }return 0;
004155D7 xor eax,eax
}
004155D9 push edx
004155DA mov ecx,ebp
004155DC push eax
004155DD lea edx,ds:[415600h]
004155E3 call @_RTC_CheckStackVars@8 (04111DBh)
004155E8 pop eax
004155E9 pop edx
004155EA pop edi
004155EB pop esi
004155EC pop ebx
004155ED add esp,21Ch
004155F3 cmp ebp,esp
004155F5 call __RTC_CheckEsp (041123Fh)
004155FA mov esp,ebp
004155FC pop ebp
004155FD ret
004155FE nop
00415600 add dword ptr [eax],eax
00415602 add byte ptr [eax],al
00415604 or byte ptr [esi+41h],dl
00415607 add byte ptr [edi+edi*8],ch
0041560A ?? ??????
}
0041560B call dword ptr [eax]
0041560D add byte ptr [eax],al
0041560F add byte ptr [esi+edx*2],dl
00415612 inc ecx
00415613 add byte ptr [ecx+72h],ah
00415616 jb _main+278h (0415618h)
汇编分析
汇编代码分析(自增/自减运算符)
这段代码展示了 C 语言中的自增(++
)和自减(--
)运算符 在汇编层面的实现方式。以下是详细分析:
1. 后置自增(i++
)
C 代码
int i = 5;
int result = i++; // result = 5, i = 6
汇编代码
mov dword ptr [i], 5 ; i = 5
mov eax, dword ptr [i] ; eax = i (eax = 5)
mov dword ptr [result], eax ; result = eax (result = 5)
add eax, 1 ; eax = eax + 1 (eax = 6)
mov dword ptr [i], eax ; i = eax (i = 6)
-
执行顺序:
-
先将
i
的旧值(5
)赋给result
。 -
然后
i
自增(i = 6
)。
-
2. 前置自增(++i
)
C 代码
int i = 5;
int result = ++i; // result = 6, i = 6
汇编代码
mov dword ptr [i], 5 ; i = 5
mov eax, dword ptr [i] ; eax = i (eax = 5)
add eax, 1 ; eax = eax + 1 (eax = 6)
mov dword ptr [i], eax ; i = eax (i = 6)
mov dword ptr [result], eax ; result = eax (result = 6)
-
执行顺序:
-
先
i
自增(i = 6
)。 -
再将
i
的新值(6
)赋给result
。
-
3. 后置自减(i--
)
C 代码
int i = 5;
int result = i--; // result = 5, i = 4
汇编代码
mov dword ptr [i], 5 ; i = 5
mov eax, dword ptr [i] ; eax = i (eax = 5)
mov dword ptr [result], eax ; result = eax (result = 5)
sub eax, 1 ; eax = eax - 1 (eax = 4)
mov dword ptr [i], eax ; i = eax (i = 4)
-
执行顺序:
-
先将
i
的旧值(5
)赋给result
。 -
然后
i
自减(i = 4
)。
-
4. 前置自减(--i
)
C 代码
int i = 5;
int result = --i; // result = 4, i = 4
汇编代码
mov dword ptr [i], 5 ; i = 5
mov eax, dword ptr [i] ; eax = i (eax = 5)
sub eax, 1 ; eax = eax - 1 (eax = 4)
mov dword ptr [i], eax ; i = eax (i = 4)
mov dword ptr [result], eax ; result = eax (result = 4)
-
执行顺序:
-
先
i
自减(i = 4
)。 -
再将
i
的新值(4
)赋给result
。
-
5. 复杂表达式中的自增/自减
C 代码
int a = 3, b = 3, c = 3, d = 3;
int result1 = a++ * 2; // result1 = 6, a = 4
int result2 = ++b * 2; // result2 = 8, b = 4
int result3 = c-- + 5; // result3 = 8, c = 2
int result4 = --d + 5; // result4 = 7, d = 2
汇编代码
(1) a++ * 2
mov eax, dword ptr [a] ; eax = a (eax = 3)
shl eax, 1 ; eax = eax * 2 (eax = 6)
mov dword ptr [result1], eax ; result1 = 6
mov ecx, dword ptr [a] ; ecx = a (ecx = 3)
add ecx, 1 ; ecx = ecx + 1 (ecx = 4)
mov dword ptr [a], ecx ; a = ecx (a = 4)
-
执行顺序:
-
先计算
a * 2
(3 * 2 = 6
)。 -
然后
a
自增(a = 4
)。
-
(2) ++b * 2
mov eax, dword ptr [b] ; eax = b (eax = 3)
add eax, 1 ; eax = eax + 1 (eax = 4)
mov dword ptr [b], eax ; b = eax (b = 4)
shl eax, 1 ; eax = eax * 2 (eax = 8)
mov dword ptr [result2], eax ; result2 = 8
-
执行顺序:
-
先
b
自增(b = 4
)。 -
然后计算
b * 2
(4 * 2 = 8
)。
-
(3) c-- + 5
mov eax, dword ptr [c] ; eax = c (eax = 3)
add eax, 5 ; eax = eax + 5 (eax = 8)
mov dword ptr [result3], eax ; result3 = 8
mov ecx, dword ptr [c] ; ecx = c (ecx = 3)
sub ecx, 1 ; ecx = ecx - 1 (ecx = 2)
mov dword ptr [c], ecx ; c = ecx (c = 2)
-
执行顺序:
-
先计算
c + 5
(3 + 5 = 8
)。 -
然后
c
自减(c = 2
)。
-
(4) --d + 5
mov eax, dword ptr [d] ; eax = d (eax = 3)
sub eax, 1 ; eax = eax - 1 (eax = 2)
mov dword ptr [d], eax ; d = eax (d = 2)
add eax, 5 ; eax = eax + 5 (eax = 7)
mov dword ptr [result4], eax ; result4 = 7
-
执行顺序:
-
先
d
自减(d = 2
)。 -
然后计算
d + 5
(2 + 5 = 7
)。
-
6. 数组索引中的应用
C 代码
int arr[] = { 10, 20, 30, 40 };
int index = 0;
int val1 = arr[index++]; // val1 = 10, index = 1
int val2 = arr[++index]; // index = 2, val2 = 30
汇编代码
(1) arr[index++]
mov eax, dword ptr [index] ; eax = index (eax = 0)
mov ecx, dword ptr [arr + eax*4] ; ecx = arr[0] (ecx = 10)
mov dword ptr [val1], ecx ; val1 = 10
mov edx, dword ptr [index] ; edx = index (edx = 0)
add edx, 1 ; edx = edx + 1 (edx = 1)
mov dword ptr [index], edx ; index = edx (index = 1)
-
执行顺序:
-
先取
arr[0]
(10
)赋给val1
。 -
然后
index
自增(index = 1
)。
-
(2) arr[++index]
mov eax, dword ptr [index] ; eax = index (eax = 1)
add eax, 1 ; eax = eax + 1 (eax = 2)
mov dword ptr [index], eax ; index = eax (index = 2)
mov ecx, dword ptr [arr + eax*4] ; ecx = arr[2] (ecx = 30)
mov dword ptr [val2], ecx ; val2 = 30
-
执行顺序:
-
先
index
自增(index = 2
)。 -
然后取
arr[2]
(30
)赋给val2
。
-
7. 未定义行为(i++ + ++i
)
C 代码
int i = 5;
// int bad_example = i++ + ++i; // 未定义行为!// 正确做法:分开写
int part1 = i++; // part1 = 5, i = 6
int part2 = ++i; // i = 7, part2 = 7
int correct_result = part1 + part2; // 5 + 7 = 12
汇编代码
(1) i++
mov eax, dword ptr [i] ; eax = i (eax = 5)
mov dword ptr [part1], eax ; part1 = eax (part1 = 5)
add eax, 1 ; eax = eax + 1 (eax = 6)
mov dword ptr [i], eax ; i = eax (i = 6)
-
执行顺序:
-
先取
i
的旧值(5
)赋给part1
。 -
然后
i
自增(i = 6
)。
-
(2) ++i
mov eax, dword ptr [i] ; eax = i (eax = 6)
add eax, 1 ; eax = eax + 1 (eax = 7)
mov dword ptr [i], eax ; i = eax (i = 7)
mov dword ptr [part2], eax ; part2 = eax (part2 = 7)
-
执行顺序:
-
先
i
自增(i = 7
)。 -
然后取
i
的新值(7
)赋给part2
。
-
(3) part1 + part2
mov eax, dword ptr [part1] ; eax = part1 (eax = 5)
add eax, dword ptr [part2] ; eax = eax + part2 (eax = 12)
mov dword ptr [correct_result], eax ; correct_result = 12
-
执行顺序:
- 计算
part1 + part2
(5 + 7 = 12
)。
- 计算
8. 多个变量混合示例
C 代码
int x = 1, y = 1;
int a = x++ + y++; // a = 1 + 1 = 2, x = 2, y = 2
int b = ++x + ++y; // x = 3, y = 3, b = 3 + 3 = 6
汇编代码
(1) x++ + y++
mov eax, dword ptr [x] ; eax = x (eax = 1)
add eax, dword ptr [y] ; eax = eax + y (eax = 2)
mov dword ptr [a], eax ; a = eax (a = 2)
mov ecx, dword ptr [y] ; ecx = y (ecx = 1)
add ecx, 1 ; ecx = ecx + 1 (ecx = 2)
mov dword ptr [y], ecx ; y = ecx (y = 2)
mov edx, dword ptr [x] ; edx = x (edx = 1)
add edx, 1 ; edx = edx + 1 (edx = 2)
mov dword ptr [x], edx ; x = edx (x = 2)
-
执行顺序:
-
先计算
x + y
(1 + 1 = 2
)。 -
然后
x
和y
分别自增(x = 2
,y = 2
)。
-
(2) ++x + ++y
mov eax, dword ptr [x] ; eax = x (eax = 2)
add eax, 1 ; eax = eax + 1 (eax = 3)
mov dword ptr [x], eax ; x = eax (x = 3)
mov ecx, dword ptr [y] ; ecx = y (ecx = 2)
add ecx, 1 ; ecx = ecx + 1 (ecx = 3)
mov dword ptr [y], ecx ; y = ecx (y = 3)
add eax, ecx ; eax = eax + ecx (eax = 6)
mov dword ptr [b], eax ; b = eax (b = 6)
-
执行顺序:
-
先
x
自增(x = 3
)。 -
然后
y
自增(y = 3
)。 -
最后计算
x + y
(3 + 3 = 6
)。
-
关键结论
运算符 | 示例 | 执行顺序 | 汇编关键指令 |
---|---|---|---|
i++ | j = i++ | 先赋值,再自增 | mov [j], eax → add eax, 1 |
++i | j = ++i | 先自增,再赋值 | add eax, 1 → mov [j], eax |
i-- | j = i-- | 先赋值,再自减 | mov [j], eax → sub eax, 1 |
--i | j = --i | 先自减,再赋值 | sub eax, 1 → mov [j], eax |
混合运算 | i++ + ++i | 未定义行为(避免使用) | 不同编译器不同实现 |
总结
-
前置运算符(
++i
/--i
):- 先修改变量,再使用新值。
-
后置运算符(
i++
/i--
):- 先使用旧值,再修改变量。
-
避免未定义行为:
- 不要在同一个表达式中对同一变量多次自增/自减。
这些示例展示了自增和自减运算符的正确用法,并解释了为什么混合使用会导致未定义行为。