【汇编 C】循环语句goto、while、dowhile、for
目录
前言
一、什么是循环语句?
二、goto语句实现循环
goto底层汇编
三、while循环语句
while底层汇编
四、dowhile语句
do while底层汇编
五、for循环
for语句的几种写法
for底层汇编
总结
结语
封面
前言
本教程内容可能会涉及到汇编,还是建议有一些汇编基础进行观看,当然我会尽力讲的通俗易懂,使用到的工具是vs2010、DTDEBUG。
一、什么是循环语句?
在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。一组被重复执行的语句称之为循环体,能否继续重复,决定循环的终止条件。循环结构是在一定条件下反复执行某段程序的流程结构,被反复执行的程序被称为循环体。 循环语句是由循环体及循环的终止条件两部分组成的。
例子:(这里就拿汇编举例吧)
首先401210位置的jmp会跳到401230的位置,然后将1,2,3,4分别放到对应的寄存器中之后再一次使用jmp跳到401210的位置。这就是个简单的循环,不过它是一个死循环,按F8一直执行会发现程序会一直循环将1,2,3,4存入寄存器。
下面就来介绍C语言中的几种循环方式。
二、goto语句实现循环
C 语言中的 goto 语句允许把控制无条件转移到同一函数内的被标记的语句。
注意:在任何编程语言中,都不建议使用 goto 语句。因为它使得程序的控制流难以跟踪,使程序难以理解和难以修改。任何使用 goto 语句的程序可以改写成不需要使用 goto 语句的写法。
测试代码goto.c:
#include <stdio.h>
#include <Windows.h>int main()
{
label1: // 用于goto跳转的标签if(1) // 1一直为真,所以程序死循环{printf("我爱你。\n"); // 每隔一秒会输出一次“我爱你”Sleep(1000); // 延时1秒,程序会停下来一秒goto label1; // goto语句跳到label1这个标签}system("pause");return 0;
}
运行可以发现,程序每隔一秒会输出一个“我爱你”,并且是一直在输出,除非我们关闭程序,这就产生了个死循环。
为什么是死循环?因为我们的条件是if(1),我们知道,如果if后面括号中的内容为真,就会执行if大括号中的内容,1一直都是真,所以会一直输出。
如果想循环五次输出“我爱你”,改一下条件即可。
代码如下:
#include <stdio.h>
#include <Windows.h>int main()
{int ii = 5;
label1: // 用于goto跳转的标签if(ii) // 1一直为真,所以程序死循环{ii=ii-1; // 持续减1,直到条件变为0就不会执行循环printf("我爱你。\n"); // 每隔一秒会输出一次“我爱你”Sleep(1000); // 延时1秒,程序会停下来一秒goto label1; // goto语句跳到label1这个标签}system("pause");return 0;
}
运行结果如下:
这就不再是循环了,执行printf("我爱你。\n")五次之后就到了system("pause");这行代码 。
那么标签能否放到goto语句下面呢?
按照C语言从上往下的执行过程来讲,肯定是不可以的。但是goto语句可以。
测试代码如下:
#include <stdio.h>
#include <Windows.h>int main()
{
label1: // 用于goto跳转的标签printf("label1\n");Sleep(1000);goto label2;label2:printf("label2\n");Sleep(1000);goto label1; // goto语句跳到label1这个标签system("pause");return 0;
}
运行结果如下:
label1和label2都有输出,所以是可以的。
以如下代码为例,我们查看一下底层goto是如何实现的。
#include <stdio.h>
#include <Windows.h>int ii = 5;int main()
{__asm mov eax,eax; // 此处设置断点label1:if(ii){ii--;printf("我爱你。\n");goto label1;}system("pause");return 0;
}
goto底层汇编
ctrl+alt+f7重新编译,f5调试,alt+8转到反汇编如下:
通过这一行代码就可以知道,goto语句就是通过jmp来实现的。jmp是跳转到指定位置,goto也是。
三、while循环语句
C语言while循环的写法
while(条件)
{
语句;
}
只要给定的条件为真,C 语言中的 while 循环语句会重复执行一个目标语句。
while语句不像goto那样需要设置标签然后跳转。
示例代码while.c:
#include <stdio.h>
#include <Windows.h>int main()
{while(1) // 条件1一直为真,所以会一直每隔1秒输出一个“我爱你”{printf("我爱你。\n");Sleep(1000); }system("pause");return 0;
}
自己运行一下看看结果。
那么while语句能不能像goto那样设置条件只执行五次呢?
可以。
while后边的小括号就是用来设置条件的,他比goto+if更灵活。
测试如下:
#include <stdio.h>
#include <Windows.h>int main()
{int ii = 5;while(ii!=0) // 等ii==0的时候就不会再循环了{ii--; // 执行一次循环ii-1printf("我爱你。\n");Sleep(1000); }system("pause");return 0;
}
运行结果如下:
转到反汇编看看while底层是如何实现的(这里可以把延时关闭,因为断点调试我们不需要延时,而且Sleep的汇编代码可能会干扰你的思路)。
代码:
#include <stdio.h>
#include <Windows.h>int main()
{int ii = 5;__asm mov eax,eax; // 此处设置断点while(ii!=0) // 等ii==0的时候就不会再循环了{ii--; // 执行一次循环ii-1printf("我爱你。\n");}system("pause");return 0;
}
while底层汇编
可以看到while语句底层也是先判断条件,然后执行完毕之后再jmp跳回原来的地址。
四、dowhile语句
dowhile和while语句的用法差不多,但是while语句是先执行再判断,相反do while是先循环再判断,这会导致即使do while的条件为假,也会执行一次。
示例代码do_while.c:
#include <stdio.h>
#include <Windows.h>int main()
{do{printf("我爱你。\n");Sleep(1000);}while(1);system("pause");return 0;
}
自己运行一下看看结果,和上面一样,也是每隔1秒输出一个“我爱你”。
那么如何做到只输出五次“我爱你”呢?
和上面while的代码都差不多,这边建议自己先试着写写,然后再看带代码,如下:
#include <stdio.h>
#include <Windows.h>int main()
{int ii = 5;do{ii--;printf("我爱你。\n");Sleep(1000);}while(ii);system("pause");return 0;
}
运行结果如下:
那么我们什么时候使用do while呢?
我们知道do while与while最大的区别就是do while无论如何都会执行一次,所以当我们需要先输入再判断的时候就可以使用do while,如下:
#include <stdio.h>
#include <Windows.h>int main()
{char getc; // 定义一个变量用来接收到字符。do{getc = getchar(); // 接收往控制台输入的字符getchar(); // 接受字符'\n',因为我们输入字符后是用回车(\n)进行确认的,但是回车'\n'也算是个字符,也需要接收putchar(getc); // 打印出接收到的字符。putchar('\n'); // 打印\n(回车)}while(getc != 'A'); // 如果我们输入的字符(getc)不是'A'就可以一直输入。system("pause");return 0;
}
运行测试如下:
如果不输入'A'就可以一直输入。
do while底层汇编
测试代码:
#include <stdio.h>
#include <Windows.h>int main()
{int ii = 5;__asm mov eax,eax; // 此处设置断点do{ii--;printf("我爱你。\n");}while(ii);system("pause");return 0;
}
汇编如下:
dowhile底层是先处理事物代码,然后判断。
五、for循环
for 循环允许您编写一个执行指定次数的循环控制结构。
for语句的结构如下:
for(表达式1;表达式2;表达式3)
{
// 需要执行的代码4
}
for语句的执行顺序是:
1 2 4 3
2 4 3
2 4 3
也就是说for循环执行完表达式1之后就会执行表达式2,然后再执行代码4,最后才执行表达式3,并且表达式1只会执行一次。并且表达式2必须包含bool类型,也就是说表达式2就相当于我们while循环中的判断真假的条件。
当然也可以不写,就是说没有判断条件,直接循环。
验证for循环语句的执行顺序,代码如下,看不懂的不用看,看结果就行:
下面for语句的第二种写法也可以验证这一观点。
for.cpp:(这里使用cpp文件,因为T2()需要返回一个bool,这是C++的类型,当然也可以用int,因为bool也属于整型)
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h> // bool类型头文件int x=1; // 定义全局变量,作为判断条件void T1()
{printf("T1\n");
}bool T2() // 这里bool也可以使用int,看自己喜欢而定
{printf("T2\n");return x--; // 使用一次该函数的返回值之后,返回值会减1
}void T3()
{printf("T3\n");
}int main()
{for(T1();T2();T3()){printf("T4\n");}system("pause");return 0;
}
这个代码的逻辑是:
首先从main函数开始运行,然后for(T1();T2();T3) { T4 }。
我们是为了验证1243的顺序,所以我们在T1、T2、T3函数中各自输出对应的数值。其中T2返回的是一个全局变量的值,我们将全局变量初始化为1。然后第一次循环的时候T2()的值就是1,会执行一次循环。第二次循环的时候判断T2的返回值时就已经是0了,不会再往下运行了,所以结果应该是T1,T2,T4,T3,T2(因为printf在return前面)。
运行结果如下:
for语句执行顺序1243和表达式1只执行一次,这两个观点验证完毕。
再次声明一次,上面的代码不需要看明白,只需要记住for执行顺序是1243即可,并且表达式1只执行1次,表达式2必须是bool类型作为判断条件。
下面for语句的第二种写法也可以验证这一观点。
for语句的几种写法
1、
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h> // bool类型头文件int main()
{for(;;){printf("我爱你。\n");}system("pause");return 0;
}
这样会一直循环,因为表达式2为空,他代表没有条件,那不就是无条件运行吗,无条件运行不就是无限循环了嘛。
2、
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h> // bool类型头文件int main()
{int ii = 0;for(;ii<100;ii++) // 0-99总共一百次。{printf("%d",ii); // 第一次输出0,也证明了1243这个顺序,因为如果先执行3(i++),那么第一次输出的应该是1。}system("pause");return 0;
}
运行结果如下:
3、
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h> // bool类型头文件int main()
{int ii; for(ii=0;ii<100;ii++) // 0-99总共一百次。{printf("%d\n",ii); // 第一次输出0,也证明了1243这个顺序,因为如果先执行3(i++),那么第一次输出的应该是1。}system("pause");return 0;
}
这就是最正规的C语言for循环写法,在外面声明ii,然后在循环里边表达式1进行初始化,表达式2进行判断,表达式3进行加减操作。
运行结果和上面一样。
可能有人会说,不是可以直接在for循环里进行int定义嘛
那是C++的写法。
如下:
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h> // bool类型头文件int main()
{for(int ii=0;ii<100;ii++) // 0-99总共一百次。{printf("%d\n",ii); // 第一次输出0,也证明了1243这个顺序,因为如果先执行3(i++),那么第一次输出的应该是1。}system("pause");return 0;
}
这样写在C++中是被允许的。但是C语言不允许,证明如下:
C++:
C语言:
以上便是for循环比较常用的写法。
for底层汇编
测试代码:
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h> // bool类型头文件int main()
{int ii;__asm mov eax,eax; // 此处设置断点for(ii=0;ii<100;ii++) // 0-99总共一百次。{printf("%d\n",ii); // 第一次输出0,也证明了1243这个顺序,因为如果先执行3(i++),那么第一次输出的应该是1。}system("pause");return 0;
}
汇编如下:
从汇编可以很容易的看出,for循环执行顺序的1243。
总结
无论是while、do while还是for,都各有应用的场景,当然goto也是,不过不建议使用goto,而且他也不那么好用是吧。虽然我们学了那么多循环,但是实际开发项目中你会发现还是for循环用的最多,所以掌握for循环是关键,当然while用的也不少。
结语
还是感谢观看!另外有错误请指出,听不懂的也请问,谢谢大家。
封面
【汇编 C】循环语句goto、while、dowhile、for相关推荐
- javascript 循环语句 while、do-while、for-in、for用法区别
本文章介绍了在学习javascript中的循环语句的用法,包while.do-while.for-in.for它们之间的区别,也是常用的循环语句了,有需要的朋友可以了解一下 前两个唯一的差别就是循环和 ...
- Java循环——for循环、while循环、do-while循环以及终止循环语句break、continue
循环 循环是指重复执行某些含有规律的指令语句的过程,循环是由反复被执行的循环语句和循环终止的条件共同组成的. 循环的格式 for循环 首先我们要说的是for循环,也是最常用的一种循 语法:for ( ...
- 用c51语言把连续字节做比较,C51优化设计之循环语句(转)
本帖最后由 ming1006 于 2013-4-6 14:49 编辑 最近在用51中因为对速度的需求很严重,于是研究了下51单片机C语言的优化问题,稍等会分享.这里先把刚才搜到的一篇不错的文章和大家分 ...
- c语言三种循环语句,C语言三种循环语句的功能等价性
C语言程序中的.bile,dowhile,for三种循环语句在实现不同形式的循环功能上各具特色及优点,从而使C语言程序的循环功能准确简洁地实现了实际问题中不同形式及过程的循环要求,本文从一般逻辑关系上 ...
- 汇编MIPS指令集 add两数相加、syscall输出字符串、bgt分支语句、ble循环语句
关于伪指令与mips指令的区别: MIPS标准定义cpu指令集的同时也定义了伪指令,伪指令可以使汇编语言可读性更好,更容易维护.每条伪指令都有对应的mips指令.汇编器负责将伪指令翻译成正式的mips ...
- [编译原理]DO-WHILE循环语句的翻译程序设计(LR(1)方法、输出四元式)C++实现
题目: DO-WHILE循环语句的翻译程序设计(LR(1)方法.输出四元式) 1 课设任务概述 初始条件: 理论:完成编译原理,数据结构.高级编程语言.汇编语言等相关课程的学习,基于计算机专业知识 ...
- C语言中的循环语句(while、dowhile、for)
文章目录 goto语句 循环语句的类型 while语句 死循环 语句的嵌套 do..while语句 for语句 goto语句 如果我们想要实现从0输出到n,如果要写0~100的话那我们就要写100个p ...
- java用do while语句逆序输出_跟我学java编程—深入理解do-while循环语句的用法
do-while循环与while循环的不同在于:它先执行循环体中的语句,然后再判断条件是否为真.如果为真则继续循环,如果为假,则终止循环.因此,do-while循环至少要执行一次循环语句.同样当有许多 ...
- 开关语句、循环语句、goto
复习: 1.数据类型:signed char 1 %hhd -128~127signed short 2 %hd -32768~32767signed int 4 %d 正负20亿signed lon ...
最新文章
- mysql 查看innodb版本,mysql中查看innodb版本的方法
- OVS vswitchd启动(三十六)
- MyBatis的useGenerateKeys的使用方法
- 前端学习(3009):vue+element今日头条管理--登录中的loding
- 【CodeForces - 1152C 】Neko does Maths(数学数论,lcm,gcd性质)
- 轻松使用计算机,职称计算机Excel辅导:简单四招让你使用Excel轻松提速
- Gerchberg–Saxton算法
- 大智慧找不到服务器,【图】大智慧官方居然没有全推服务器请老师解决_股票软件,股票指标,炒股,股票论坛,选股公式_股票软件技术交流论坛_理想论坛 - 股票论坛...
- shell脚本循环嵌套
- 同步异步线程进程的一些思考
- 每台计算机ip地址,每台电脑均要设置IP地址,究竟什么是IP地址,到底有什么用呢?...
- 使用注册表屏蔽任意按键或改键
- 【安卓按键精灵自动取色(可用于比色,多点找色,找图实现)】
- download.php是什么文件,qmdownload是什么文件?
- 落地SQL审核的迭代思路
- 视图存储过程存储函数
- 解决excel数据透析表计算类型没有非重复计数选项
- 英文学习20180327
- JAVA开发人员必备的免费JSP空间
- 【华为OD机试真题 JS】用连续自然数之和来表达整数