新书推荐:7.5 goto、break、continue语句

本节必须掌握的知识点:

        示例二十六

        代码分析

        汇编解析

        示例二十七

        代码分析

        汇编解析

7.5.1 示例二十六

goto语句:无条件转移语句。

语法格式:

goto label;

label :

代码;

●语法解析:

执行到goto语句时,则无条件跳转到label标记。其实就是汇编无条件跳转指令JMP,但是与JMP指令又有区别。

示例代码二十六

●第一步:分析需求,设计程序结构框架。

分析需求:构建一个while循环语句,当n > m时,重复执行whiler循环语句,重复语句块设了一个地址标号label:,while语句外的goto label;语句直接跳转到label地址标号处执行。

设计程序结构框架:goto语句跳入while循环结构内的重复语句。

 ●第二步:数据定义,定义恰当的数据结构;

       int n;//定义一个int类型的整型局部变量n,并将其初始化为1。

       int m;//定义一个int类型的整型局部变量m,并将其初始化为2。

●第三步:分析算法。

当执行goto语句时,直接跳过了while语句的条件判断,执行重复语句块内的n++;语句。

●第四步:编写伪代码,即用我们自己的语言来编写程序。

int main(void) {

    定义一个int类型整型循环变量n=1和m=2;

    goto label;跳转到label地址标号处

    while (n > m){ //条件为真执行重复语句块

        调用printf函数打印信息:"这句话是执行不到的"       

    label

        n++

        调用printf函数打印信息:("n=%d\n",n)        

    }                   

    调用printf函数打印信息"这句话可以执行到吗?\n" 

    system("pause");

    return 0;                                                                                                    

}

●第五步:画流程图,使用Visio、Excel或者其他绘图工具绘制算法流程和逻辑关系图; 如图7-5所示。

图7-5 示例二十六goto语句

●第六步:编写源程序,其实就是将我们的伪代码翻译成计算机语言;

/*

   goto语句

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int n = 1, m = 2;

    goto label; //跳转到label地址标号处

    while (n > m)

    {

        printf("这句话是执行不到的");

label: n++;

        printf("n=%d\n", n);

    }

    printf("这句话可以执行到吗?\n");

    system("pause");

    return 0;

}

●输出结果:

n=2

这句话可以执行到吗?                                                 

7.5.2 代码分析

按照while语句的语法格式,是先判断条件再执行语句块,由于我们加了goto语句打乱了while语句的正常执行流程。

1.申请变量n、m,并赋值为n=1,m=2;

2.执行goto语句,无条件跳转到label标记的代码处;

3.执行label 标记对应的代码处,n++;【此时我们看到代码并没有执行while语句对应的表达式,也没有判断表达式的真假,而是直接跳到了while语句块内执行label标记】。

4.输出n的值,1+1=2,n=2

5.此时在判断while语句表达式是否为真,2=2,条件为假,退出循环体

6.执行printf("这句话可以执行到吗?");

7.结束程序。

 

结论

1.goto语句为无条件跳转语句,跳转到goto后的地址标号处。

2.goto语句破坏了循环结构,也为退出循环提供了一个便捷通道。

3.goto语句中的地址标号只能在同一个函数内,不可以是另一个函数中的地址标号。

7.5.3 反汇编解析

汇编代码

;C标准库头文件和导入库

include vcIO.inc

.data

n sdword  1

m sdword  2

.const    

szMsg1 db "这句话是执行不到的",0dh,0ah,0

szMsg2 db "n = %d",0dh,0ah,0

szMsg3 db "这句话可以执行到吗?",0dh,0ah,0

.code     

start:

       mov eax,m

       jmp label1

       .while n > eax

              invoke printf,offset szMsg1 

label1:

              inc sdword ptr n;

              invoke printf,offset szMsg2,n

       .endw

       invoke printf,offset szMsg3 

       ;     

       invoke _getch

       ret                       

end start

●输出结果:

n=2这句话可以执行到吗?

在上述汇编代码中,jmp label1语句对应C语言中的“goto label;”语句,跳转到地址标号label1处。紧接着.while高级汇编伪指令对应C语言中的while循环语句,不需要再多解释。

反汇编代码

           int n = 1, m = 2;

001C1046  mov         dword ptr [n],1 

001C104D  mov         dword ptr [m],2 

    goto label;//跳转到label地址标号处

001C1054  jmp         label (01C106Bh)  ;无条件跳转到label地址处

    while (n > m)

001C1056  mov         eax,dword ptr [n] 

001C1059  cmp         eax,dword ptr [m] 

001C105C  jle         label+1Ch (01C1087h;n<=m时,(n=2)跳转到01C1087h地址处

    {

        printf("这句话是执行不到的");

001C105E  push        1C3000h 

    {

        printf("这句话是执行不到的");

001C1063  call        printf (01C10B0h) 

001C1068  add         esp,4 

    label: n++;

001C106B  mov         ecx,dword ptr [n] 

001C106E  add         ecx,1 

001C1071  mov         dword ptr [n],ecx 

        printf("n=%d\n", n);

001C1074  mov         edx,dword ptr [n] 

001C1077  push        edx 

001C1078  push        1C3014h 

001C107D  call        printf (01C10B0h) 

001C1082  add         esp,8 

    }

001C1085  jmp         main+16h (01C1056h)  ;无条件跳转到while语句起始位置

    printf("这句话可以执行到吗?\n");

001C1087  push        1C301Ch 

001C108C  call        printf (01C10B0h) 

001C1091  add         esp,4 

    system("pause");

001C1094  push        1C3034h 

001C1099  call        dword ptr [__imp__system (01C2078h)] 

001C109F  add         esp,4 

    return 0;

       上述反汇编代码将goto语句翻译为无条件跳转指令jmp语句,while语句翻译为CMP/JCC指令+JMP无条件跳转指令。请读者参照代码注释,分析程序的执行流程。

break语句

在循环中存在break语句,执行它相当于退出循环,跳转到循环语句块外的下一条语句地址处,详见“实验四十九for语句表现形式2的示例代码7-3-3.c”。

在6.3节switch语句中必然包含break语句。请读者回顾示例代码二十一的反汇编代码,查看break语句的跳转地址(跳出了switch语句块)。

此外,在7.1节do while语句的实验四十二中,do while语句嵌套的switch语句中也包含break语句。希望读者认真分析其反汇编代码,查看break语句的跳转地址。

基于上述break语句的示例,本节将不再重复介绍break语句的实现。

7.5.4 示例二十七

continue语句

我们用例子来看continue语句的用法。

示例代码二十七

●第一步:分析需求,设计程序结构框架。

分析需求:构建一个for循环语句,当循环变量i <= 10时,重复执行for循环语句块,重复语句块嵌套了一个if条件语句块,当循环变量i%2的模不为0时,执行if语句块,当执行到continue语句时,跳出本轮for循环,i++后执行下一轮循环。

设计程序结构框架:for语句嵌套if语句块,if语句块内的continue语句打断本轮循环,直接执行下一轮循环。

●第二步:数据定义,定义恰当的数据结构;

for语句的条件表达式中定义循环变量int i=1;

●第三步:分析算法。

当执行for循环语句时,如果if语句的条件判断为真,执行if语句块,当执行到continue语句时退出本轮for循环,进入下一轮循环。如果if语句条件表达式为假,执行printf("i = %d\n", i);

●第四步:编写伪代码,即用我们自己的语言来编写程序。

int main(void) {

    定义一个for循环语句;    表达式1:int i=1;

    表达式2:i <= 10;

    表达式3:i++;

    for (表达式1;表达式2;表达式3){ //条件为真执行重复语句块

        if(i%2)条件为真执行if语句块{

      调用printf函数打印信息("%d\n", i);        

      continue;// 执行到continue;时后面的printf(“■”);将不执行,被跳过。

      调用printf函数打印信息("■");

      }

      调用printf函数打印信息("i = %d\n", i);   

     }                   

     system("pause");

    return 0;                                   

}

●第五步:画流程图,使用Visio、Excel或者其他绘图工具绘制算法流程和逻辑关系图;如图7-6所示。

图7-6 示例二十七continue语句

●第六步:编写源程序,其实就是将我们的伪代码翻译成计算机语言;

/*

   continue语句

*/

#include <stdio.h>

#include <stdlib.h>                                

int main(void) {

    for (int i = 1; i <= 10; i++)          

    {

        if (i % 2)

        {

            printf("%d\n", i);

            continue;//执行continue;后面的printf(“■”);将不执行,被跳过。

            printf("■");

        }

        printf("i = %d\n", i);

    }

    system("pause");

    return 0;

}

●输出结果:

1

i = 2

3

i = 4

5

i = 6

7

i = 8

9

i = 10

请按任意键继续. . .

7.5.5 代码分析

1.当循环变量i=1时,for循环条件表达式为真,执行for循环语句块;

2.循环变量i=1时,i%2的模为1,if语句条件表达式为真,执行if语句块;

首先执行printf("%d\n", i);,然后执行continue语句,参考continue语句的流程图,我们清晰地看到continue语句跳过了printf("■");语句,直接跳到了n++;语句,然后开始下一轮循环。

3.当循环变量i=2时,for循环条件表达式为真,执行for循环语句块;

4.循环变量i=2时,i%2的模为0,if语句条件表达式为假,执行printf("i = %d\n", i);然后执行n++;语句,开始下一轮循环。

7.5.6 汇编解析

汇编代码

;C标准库头文件和导入库

include vcIO.inc

.data

i sdword  ?

.const    

szMsg1 db "%d",0dh,0ah,0

szMsg2 db "■",0

szMsg3 db "i = %d",0dh,0ah,0

.code     

start:

       mov sdword ptr i,1

next1:

       .while i <= 10

              mov eax,i

              mov ebx,2

              cdq

              idiv ebx

              .if edx

                     invoke printf,offset szMsg1,i

                     jmp next2      ;continue语句

                     invoke printf,offset szMsg2

              .else

                     invoke printf,offset szMsg3,i      

              .endif

next2:           

              inc sdword ptr i;

              jmp next1

       .endw

       ;     

       invoke _getch

       ret                       

end start

●输出结果:

1

i = 2

3

i = 4

5

i = 6

7

i = 8

9

i = 10

 

结论

上述汇编代码使用.while和.if/.else语句,等同于C语言中的for语句和if/else语句。比较有意思的是:汇编代码使用jmp无条件跳转指令实现了continue语句。对比C语言,汇编代码清晰的标注了跳转的地址标号,而C语言省略了地址标号,仅此而已。

反汇编代码

           for (int i = 1; i <= 10; i++)

01341044  mov         dword ptr [ebp-4],1  ;表达式1:循环变量i初始化为1

    for (int i = 1; i <= 10; i++)

0134104B  jmp         main+16h (01341056h;跳转到表达式2

0134104D  mov         eax,dword ptr [ebp-4] ;表达式3:i++

01341050  add         eax,1 

01341053  mov         dword ptr [ebp-4],eax 

01341056  cmp         dword ptr [ebp-4],0Ah ;表达式2:条件判断语句

0134105A  jg          main+63h (013410A3h;如果变量i>10则退出循环

    {

        if (i % 2)

0134105C  mov         ecx,dword ptr [ebp-4] ;取变量i的值送入ecx寄存器

0134105F  and         ecx,80000001h        ;这里是否还有印象?

01341065  jns         main+2Ch (0134106Ch;正整数则跳转

01341067  dec         ecx                 ;判断负整数

01341068  or          ecx,0FFFFFFFEh 

0134106B  inc         ecx 

0134106C  test        ecx,ecx 

0134106E  je          main+50h (01341090h;ecx为0(偶数)跳转到01341090h地址处

        {

            printf("%d\n", i);奇数则打印信息

01341070  mov         edx,dword ptr [ebp-4] 

01341073  push        edx 

01341074  push        1343000h 

01341079  call        printf (013410C0h) 

0134107E  add         esp,8 

        continue;//执行到continue;时后面的printf(“■”);将不执行,被跳过。

01341081  jmp         main+0Dh (0134104Dh;无条件跳转到循环语句的表达式3

            printf("■");

01341083  push        1343004h 

01341088  call        printf (013410C0h) 

0134108D  add         esp,4 

        }

        printf("i = %d\n", i);

01341090  mov         eax,dword ptr [ebp-4] 

01341093  push        eax 

01341094  push        1343008h 

01341099  call        printf (013410C0h) 

0134109E  add         esp,8 

    }

013410A1  jmp         main+0Dh (0134104Dh;无条件跳转到循环语句的表达式3

    system("pause");

013410A3  push        1343010h 

    system("pause");

013410A8  call        dword ptr [__imp__system (01342078h)] 

013410AE  add         esp,4 

    return 0;

       请读者仔细阅读代码注释,此处不再赘述。

 

总结

1.如果continue语句是在for语句大括号内,当continue语句被执行时,表示结束一轮循环、直接进入下一循环。也就是说continue语句后面的语句不被执行。

2.正确使用goto、break和continue语句时,这两个语句的执行速度会比结构化程序设计技术的执行速度更快。

3.break和continue语句用于改变控制流。当while、for、do/while或switch语句中执行break语句时,break语句会造成程序从语句退出,程序会接着执行该语句之后的第一条语句。

4.break语句的常规用途时从循环语句中退出,或跳过switch语句中剩余部分。

5.continue语句的作用是跳过剩余语句,并执行循环的下一次迭代。

练习

1、使用goto语句,求 1+2+3+......+100的和。

2、请修改示例代码二十七,不使用continue语句,实现相同的功能。

 3、请修改“实验四十九for语句表现形式2的示例代码7-3-3.c”,不使用break语句实现相同的功能。

本文摘自编程达人系列教材《汇编的角度——C语言》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/18312.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jetpack架构组件_1.基本知识

1.什么是Jetpack&#xff1f; Jetpack 是一个由多个库组成的套件&#xff0c;可帮助开发者遵循最佳做法、减少样板代码并编写可在各种 Android 版本和设备中一致运行的代码&#xff0c;让开发者可将精力集中于真正重要的编码工作。Jetpack 包含一系列 Android 库&#xff0c;它…

pcdn服务器应该怎么配?

要配置PCDN&#xff08;Private Content Delivery Network&#xff09;服务器&#xff0c;可以按照以下步骤进行&#xff1a; 需求分析&#xff1a;明确业务需求&#xff0c;确定所需的CDN功能和性能参数。这包括预期的流量、负载、内容类型、目标用户群体等。 硬件选择&#…

VCRUNTIME140_1.dll丢失是怎么回事?vcruntime140_1.dll无法继续执行代码的处理方法

VCRUNTIME140_1.dll丢失是怎么回事&#xff1f;问出这样的问题的人&#xff0c;一般是遇到vcruntime140_1.dll无法继续执行代码的问题了&#xff0c;找不到VCRUNTIME140_1.dll文件&#xff0c;那么程序就肯定是启动不了的&#xff0c;程序的启动是需要VCRUNTIME140_1.dll文件的…

Java进阶学习笔记1——课程介绍

课程适合学习的人员&#xff1a; 1&#xff09;具备一定java基础的人员&#xff1b; 2&#xff09;想深刻体会Java编程思想&#xff0c;成为大牛的人员&#xff1b; 学完有什么收获&#xff1f; 1&#xff09;掌握完整的Java基础技术体系&#xff1b; 2&#xff09;极强的编…

行为设计模式之状态模式

文章目录 概述定义结构图 2.代码示例小结 概述 定义 状态模式(state pattern)的定义: 允许一个对象在其内部状态改变时改变它的行为。 对象看起来似乎修改了它的类。 状态模式就是用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题.。状态模式将一个对象的状态…

New Phytologist:杨树特有miRNA在调控杨树抗旱中的分子机制

2024年3月6日&#xff0c;林木遗传育种全国重点实验室、北京林业大学生物科学与技术学院尹伟伦与夏新莉教授课题组在New Phytologist&#xff08;中科院一区&#xff0c;影响因子9.4&#xff09;期刊发表了题为“The miR6445-NAC029 module regulates drought tolerance by reg…

selenium 学习笔记(一)

pip的安装 新建一个txt curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py 把上面的代码复制进去后&#xff0c;把后缀名改为.bat然后双击运行 当前目录会出现一个这个文件 然后在命令行pyhon get-pip.py等它下好就可以了selenium安装 需要安装到工程目…

云计算-Lambda事件 (Lambda Events)

检索事件信息 (Retrieving Event Information) 在上一个主题中&#xff0c;我们已经看到了如何创建一个Lambda函数、添加handler、添加触发器和配置执行策略。在本主题中&#xff0c;我们将对其进行扩展。到目前为止&#xff0c;我们看到的handler应用非常简单&#xff0c;但我…

linux 定时执行shell、python脚本

在linux里设置定时执行一般是用crontab&#xff0c;如果没有的话&#xff0c;可以先安装&#xff1a; 安装 查看是否安装 cron -v # 对于基于Debian的系统&#xff08;如Ubuntu&#xff09; sudo apt-get install cron# 对于基于RedHat的系统&#xff08;如CentOS&#xff…

【5】:三维到二维变换(模型、视图、投影)

观测变换 物体上某一点的坐标变换顺序&#xff1a;M->V->P MVP变换用来描述视图变换的任务&#xff0c;即将虚拟世界中的三维物体映射&#xff08;变换&#xff09;到二维坐标中。 1.Model Transformation 模型变换 场景中每个物体上的某一点&#xff0c;从局部坐标系…

YoloV8实战:各种图绘制汇总(mAP50、mAP50-95、loss、PR_curve、F1_curve)|科研必备|绘图神器

摘要 本文的内容是告诉大家如何绘制mAP50、mAP50-95、loss、PR_curve、F1_curve等图像,方便大家写论文。 绘制mAP50、mAP50-95、loss等图。 先上效果,如下图: 首先将,训练的result.csv汇总到一个文件夹下面(这样方便寻找),要不然找起来太麻烦。如下图: 我都放到re…

Pyinstaller打包exe文件解决指南

打包命令 打包 Python 文件 输入如下格式的命令即可 默认命令 Pyinstaller 文件名.py Pyinstaller -option1 -option2 -... 要打包的文件 Pyinstaller 文件名.pyPyinstaller -option1 -option2 -... 要打包的文件 参数选项比较多&#xff0c;这里我列一个表&#xff1a;…

[C#]winform部署官方yolov10目标检测的onnx模型

【框架地址】 https://github.com/THU-MIG/yolov10 【算法介绍】 今天为大家介绍的是 YOLOv10&#xff0c;这是由清华大学研究团队最新提出的&#xff0c;同样遵循 YOLO 系列设计原则&#xff0c;致力于打造实时端到端的高性能目标检测器。 方法 创新 双标签分配策略 众所…

灯塔工厂产业数字化平台解决方案(50页PPT)

方案介绍&#xff1a; 随着工业4.0和智能制造的快速发展&#xff0c;传统工厂正面临着转型升级的迫切需求。为了提升生产效率、优化资源配置、增强市场竞争力&#xff0c;我们推出了灯塔工厂产业数字化平台解决方案。该方案旨在通过先进的信息技术手段&#xff0c;将传统工厂转…

蒙特卡洛法求解机械臂工作空间(以IRB4600型工业机械臂为例)

1. 概念 工作空间是衡量机器人工作能力的一个重要的运动学指标&#xff0c;蒙特卡洛法是一种随机模拟方法&#xff0c;用于在计算机上估计某些统计量&#xff0c;对于要估计的统计量&#xff0c;通过模拟大量的随机抽样&#xff0c;并计算这些样本的随机值来估算这个统计量的值…

数字信号处理实验三:IIR数字滤波器设计及软件实现

一、实验目的 1. 掌握MATLAB中进行IIR模拟滤波器的设计的相关函数的应用&#xff1b; 2. 掌握MATLAB的工具箱中提供的常用IIR数字滤波器的设计函数的应用&#xff1b; 3.掌握MATLAB的工具箱中提供的模拟滤波器转数字滤波器的相关的设计函数的应用。 二、实验内容 本实验为…

CC1310 Debug interface is locked

XDS110连接CC1310板子&#xff0c;打开Smart RF 弹出窗口如下&#xff1a; 解决办法&#xff1a; 1 打开SmartRF Flash Programmer 2 选择连接的设备CC1310, 弹出如下窗口&#xff0c;点击OK。 3 点击Tools图标&#xff0c;选择CC26XX/CC13XX Forced Mass Erase。 4 在弹出的…

Windows11系统安装QEMU虚拟化软件

Windows11系统安装QEMU虚拟化软件 QEMU软件是一个通用的开源机器模拟器和虚拟机。本文档适用于在Windows 11系统平台上安装QEMU软件。 1. 安装准备 1.1 安装平台 Windows 11 1.2. 软件信息 软件名称软件版本安装路径QEMUQEMU-8.2.93D:\qemu 1.3软件下载 QEMU官网官网下…

【全开源】西陆家政系统源码小程序(FastAdmin+ThinkPHP+原生微信小程序)

打造高效便捷的家政服务平台 一、引言&#xff1a;家政服务的数字化转型 随着人们生活节奏的加快&#xff0c;家政服务需求日益增长。为了满足广大用户对高效、便捷的家政服务的需求&#xff0c;家政小程序系统源码应运而生。这款源码不仅能够帮助家政服务提供商快速搭建自己…

关于本人VIP付费文章说明

郑重声明&#xff1a;我写博客只是为了记录分享经验 自从上次写完数据结构系列后我就一直没有登陆&#xff0c;目前也没打算继续开新内容。今天偶然发现我之前写的文章被设为vip文章&#xff0c;要vip解锁才能看&#xff0c;我很确定当初我发布的时候选择的是公开&#xff0c;…