【汇编 C】循环语句goto、while、dowhile、for

article/2025/9/15 22:04:55

目录

前言

一、什么是循环语句?

二、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用的也不少。

结语

        还是感谢观看!另外有错误请指出,听不懂的也请问,谢谢大家。

封面

 


http://chatgpt.dhexx.cn/article/FZLsjxv4.shtml

相关文章

【C语言】循环语句(do while循环)

简单不先于复杂&#xff0c;而是在复杂之后。 目录 do while循环 do 语句的用法 执行流程 do语句的特点 go to语句 do while循环 do 语句的用法 while循环和for循环都是入口条件循环&#xff0c;即在循环的每次迭代之前检查测试条件&#xff0c;所以有可能根本不执行循环…

while和do while的用法区别

前言 在上一篇文章中&#xff0c;壹哥给大家讲解了循环的概念&#xff0c;并重点给大家讲解了for循环的使用。但在Java中&#xff0c;除了for循环之外&#xff0c;还有while、do-while、foreach等循环形式。今天小千就再用一篇文章&#xff0c;给大家讲解while循环的使用。 本文…

循环语句—do…while循环

目录 3.do……while循环语句 3.1do……while循环语句格式 3.2三种循环的区别 3.3总结三种循环的区别 3.do……while循环语句 3.1do……while循环语句格式 基本格式&#xff1a; do { 循环体语句&#xff1b; } while&#xff08;条件判断语句&#xff09;&#xff1b; …

While语句与do...while语句

循环结构之while语句&#xff1a; while(表达式&#xff09; {语句} 注意&#xff1a;1.while循环的特点是先判断条件表达式&#xff0c;后执行循环体语句。 2.“语句”就是循环体。循环体可以是一个简单的语句&#xff0c;可以是复合语句&#xff08;用花括号括起来的若干语…

C/C++之while(do-while)详细讲解

目录 while循环有两个重要组成部分&#xff1a; while 是一个预测试循环 无限循环 do-while 循环 while循环有两个重要组成部分&#xff1a; 进行 true 值或 false 值判断的表达式&#xff1b;只要表达式为 true 就重复执行的语句或块&#xff1b; 图 1 显示了 while 循环的…

do{...}while(0)的用法

首发于微信公众号&#xff1a;【码农在新加坡】&#xff0c;欢迎关注。 个人博客网站&#xff1a;do{...}while(0)的用法 零.导引 第一次见到 do{...}while(0)是在学习libevent的时候&#xff0c;看到里面有很多类似 #define TT_URI(want) do { \char *ret evhttp_uri_…

if,while选择结构和while,dowhile,for循环的使用

什么是if和while选择结构 if 选择结构是根据句条件判断之后再做处理的一种语法结构&#xff0c; 语法如下&#xff1a; while是一种先判断再执行循环体的结构&#xff1b; 当while循环条件为真时才执行循环体&#xff0c;然后再判断循环条件&#xff0c;如果条件为真&#xf…

while及do while语句

编写程序时&#xff0c;许多问题都要用到循环控制。循环结构也是结构化程序设计的基本结构之一&#xff0c;因此熟练地掌握循环结构是程序设计最基本的要求。While循环、do while循环、for循环语句&#xff0c;3种循环语句在一般情况下可以相互转换 While 及dowhile语句 Whil…

代码执行顺序之循环执行:forwhiledowhile嵌套循环

代码执行顺序之循环执行 循环执行的分类 for循环while循环dowhile循环 for循环 语法&#xff1a; for(循环初始化表达式&#xff1b;循环条件表达式&#xff1b;循环后的操作表达式){ ​ // 循环体 } 执行步骤分析&#xff1a; 循环初始化表达式最先执行&#xff0c;并且只执…

dowhile的学习

dowhile的学习 dowhile 的概念及他与while的区别 package javaxunhuanjiegou; ​ public class DoWhile {public static void main(String[] args) {int a 0;int sum 0;do {sum sum a;a;} while (a < 100);System.out.println(sum);} } ​ 我们来跟直观的感受一下 于…

循环结构 --> do while循环

do while循环 do {循环体;} while(条件表达式);执行循环体 > 判断条件表达式是否成立> 若成立&#xff0c;则执行循环体 > 判断条件表达式是否成立> 若不成立&#xff0c;则循环结束do while循环主要用于至少执行一次循环体的场合中。package demo;/*编程实现do wh…

do while循环和whil循环(内含流程图)

C语言的三大循环语句除去for循环语句还剩下do while和while循环&#xff0c;因为这两个很相似所以这里放在一起讲解。希望读完本文能对你有所帮助。 do while循环和whil循环 一、do...while二、while 一、do…while do while的语法循环结构如下所示。 do while的逻辑循环结构…

SQL中join操作后面的on与where的区别

join关键字的作用是将多个表按一定的条件联合起来&#xff0c;从而可以实现从多个表中获取数据 在join后面可以接on条件和where条件&#xff0c;在这里我主要就是说这两者之间的差别 建立两张简单的用来测试的表并添加数据&#xff0c;如下所示&#xff0c;一张表名为id_name…

MySql 各种join的使用方法

具体详解如下 1 INNER JOIN(内连接) SELECT * FORM TABLE_A A INNER JOIN TABLE_B B ON A.KEY B.KEY 2 LEFT JOIN (左连接) SELECT * FORM TABLE_A A LEFT JOIN TABLE_B B ON A.KEY B.KEY 3 RIGHT JOIN (右连接) SELECT * FROM TABLE_A A RIGHT TABLE_B B ON A.KE…

SQL 中JOIN ON 的AND条件设置

关于在A LEFT JOIN B ON A.id B.id 后面跟AND 条件的测试。 有如下的结构数据&#xff1a; 注意此LEFT ON 跟AND 限制A表的场景&#xff1b; dat a.sql 1.43KB 有如下的表结构 使用SQL进行查询&#xff1a; &#xff08;1&#xff09;SELECT * FROM table_name a LEFT J…

简单说说SQL中Join的使用

最近工作中&#xff0c;遇到了一起由于慢SQL引起DB CPU > 90% &#xff0c;数据库hang住。。最终导致其他业务查询统统失败。 细看下来是由于几张大表Join关联查询引起的&#xff0c;故障本身很常见&#xff0c;不过让我想到有必要讲讲如何规避Join的问题。 以下的讨论都是基…

SQL-JOIN全解析

SQL-JOIN全解析 一、SQL JOIN的作用是什么&#xff1f;二、四种JOIN的区别三、如何使用各种join&#xff08;一&#xff09;准备测试数据&#xff08;二&#xff09;左连接&#xff08;三&#xff09;右连接&#xff08;四&#xff09;内连接&#xff08;五&#xff09;外连接 …

SQL中join语句详解

1.inner join(内连接) 只返回匹配的行。 select * from table_a a inner join table_b b on a.name b.name 2.left join(左外连接) 返回左表的全部数据&#xff0c;和右表中满足on条件的行&#xff0c;如果左表的行在右表中没有匹配的数据&#xff0c;那么这一行中右表对应…

SQL Server 数据库常用操作:多表联查(JOIN...ON语句的使用)

1.使用传统连接方式查询 (1). 有两张表Book(BookID,BookName,TypeID,AuthorID,…)&#xff0c;BookType(TypeID,TypeName)&#xff0c;查询每本书的书名和图书类型。 SELECT BookName, TypeName FROM Book, BookType WHERE Book.TypeID BookType.TypeID(2). 有三张表Book(Boo…

Oracle SQL中join方式总结

在ORACLE数据库中&#xff0c;表与表之间的SQL JOIN方式有多种&#xff08;不仅表与表&#xff0c;还可以表与视图、物化视图等联结&#xff09;。SQL JOIN其实是一个逻辑概念&#xff0c;像NEST LOOP JOIN、 HASH JOIN等是表连接的物理实现方式。 为了更直观的了解以上join方式…