一. while
提出问题
- while语句用什么指令进行跳转的呢?答:jmp,je指令
- 在哪个地方存放这条指令呢?
C++
ListNode* deleteDuplicates(ListNode* head) {
if (!head) {
return head;
}
ListNode* cur = head;
while (cur->next) {
if (cur->val == cur->next->val) cur->next = cur->next->next;
else cur = cur->next;
}
return head;
}
设计实验:
int main()
{
int* pWorth = NULL;
while (pWorth)
{
std::cout << "有意义";
}
}
汇编
mov dword ptr [ebp-4],0
cmp dword ptr [ebp-4],0
je 00871026
push 873138h
mov eax,dword ptr ds:[00873068h]
push eax
call 008710B0
add esp,8
jmp 0087100B
当执行完第二行的cmp指令后,ZF位的值改变了,说明ZF影响je指令是否会跳转
发现规律
- 当ZF为1,je指令会被执行,使EIP的值改变,从而跳转到指定的内存地址;当ZF为0,je指令只会使EIP寄存器+2;
知识点:
- ZF位:零标志位,代表指令运算的结果为零时会设置为1,代表了两个数是否相等
得出结论
- while语句的本质是mov , cmp, je, jmp指令的组合
- jmp指令的作用是跳到while语句的首地址,以实现重复执行指令
- je指令的作用是跳转到jmp指令后面的的地址,避免死循环的结果,需要与cmp指令,mov指令配合使用
- 注意点:while代码块里面的代码中必须要有让循环退出的数据或break语句,否则会使程序进入****死循环状态
二.do{}while()
猜测:该语句也有cmp,je,mov指令,只不过跟jmp指令放在了一起
C++
int main()
{
int* pWorth = NULL;
do
{
std::cout << "有意义";
}while (pWorth == NULL);
}
汇编
00791002 in al,dx
00791003 push ecx
00791004 mov dword ptr [ebp-4],0
0079100B push 793138h
00791010 mov eax,dword ptr ds:[00793068h]
00791015 push eax
00791016 call 007910B0
0079101B add esp,8
0079101E cmp dword ptr [ebp-4],0
00791022 je 0079100B
00791024 xor eax,eax
00791026 mov esp,ebp
00791028 pop ebp
00791029 ret
发现规律:
do while 语句是由cmp指令,跳转指令(jne,je)组合而成的,而跳转的地址是代码块的首地址
得出结论:
- do while
代码块
里面的指令
必须要有改变判断变量值
的代码或break语句
,否则会造成程序的死循环
三. for(){}
提出问题:
- 在括号里的变量i为什么在for循环外不能使用?
- i++指令什么地方执行呢?猜测:在jmp指令后面 答案:
- 第一个分号前的代码会被多次执行吗?
C++
vector<int> twoSum(vector<int>& nums, int target){
vector<int> ret;
for (int i = 0; i < nums.size(); i++)
{
for (int y = i + 1; y < nums.size(); y++)
{
if (nums[i] + nums[y] == target) {
ret.push_back(i);
ret.push_back(y);
break;
};
}
}
return ret;
}
0x0 从
汇编
的角度去看for语句
jae指令
当ZF = 0时,CF = 0时时,jae指令会跳转到对应的内存地址
当ZF = 1时,CF = 0时时,jae指令会跳转到对应的内存地址
当ZF = 0时,CF = 1时时,jae指令会使EIP+2
得出结论
- for语句由以下模块组成的汇编指令, 第一次执行指令到i++,会跳过直接比较
- 当程序符号条件就进行重复执行指令阶段,直到数据不符合条件为止,因此代码块里必须有让条件不符合的数据或break语句
- for循环第一次执不会执行i++,会JMP到比较指令,根据比较结果决定是否执行代码块,然后才会执行i++,再进行判断;这是for循环的特点,设计的时候需要考虑索引值的问题
0x1 从
设计
的角度去看for语句
红色线条的思考:循环过程需要用到的局部变量
的初始值
是什么呢?
蓝色线条的思考:每一次的跳转
需要我们去做什么样的重复行为
呢?
黑色线条的思考:第一次的跳转
和以后的跳转
需要我们分别去做什么样的比较行为
呢?
第一个方框内容的思考:循环过程
需要不断做的操作是什么呢?
应用场景:
内存
里的某个变量
的值不在某个值范围
时,要反复
去执行同一段指令