machine code中的条件控制control flow和switch语句,循环Loop

news2024/10/2 0:32:54

上篇写了machine code基本知识概念,这篇再总结一下其中的流控制、条件判断,循环等实现。

一段machine code引出

在machine code中,通场使用jmp指令来跳转到某个代码块。比如一个机器码可能长这样:

decision:
    subq $8, %rsp
    testl %edi, %edi
    je .L2
    call op1
    jmp .L1
.L2:
    call op2
.L1:
    addq $8, %rsp
    ret

随着逐行执行,一旦碰到了jmp指令,就可以直接到对应的代码块而跳过中间的部分,就像C语言中的GOTO一样。

等等,那je是啥?在讲je之前,先写一下条件码 Condition Codes.

Condition Codes

条件码(Condition Codes)是一组用于表示操作结果状态的标志位。这些标志位通常存储在单比特寄存器中(可以认为是额外于之前介绍的%rax,%rbx之类的小寄存器)。

  1. CF(Carry Flag):进位标志,用于无符号数运算。
  2. SF(Sign Flag):符号标志,用于有符号数运算。
  3. ZF(Zero Flag):零标志,表示运算结果是否为零。
  4. OF(Overflow Flag):溢出标志,用于有符号数运算。

在 GDB 调试器中,这些标志位会被打印为一个名为 "eflags" 的寄存器,比如示:

eflags 0x246 [ PF ZF IF ] Z set, CSO clear

在进行算术运算时,条件码通常会被隐式设置(作为运算的附加结果)。以 addq Src, Dest 操作为例,该操作执行加法运算:t = a + b。在这个过程中,条件码会根据以下规则自动set:

  1. CF(Carry Flag):当最高有效位产生进位时set(表示无符号溢出)。
  2. ZF(Zero Flag):当 t == 0 时set。
  3. SF(Sign Flag):当 t < 0 时set(表示结果为负数)。
  4. OF(Overflow Flag):当发生补码(有符号)溢出时set。这种情况包括:
    • 当 a > 0b > 0 且 t < 0 时。
    • 当 a < 0b < 0 且 t >= 0 时。

比较指令(cmp)和 测试指令(test)

可以注意到,在一开始的示例代码中,je上面还有一个testl命令。这里就要引出cmp和test。

cmp 指令用于比较两个操作数 a 和 b。其执行过程如下:

  1. 计算 b - a(与 sub 指令相同)。
  2. 根据结果设置条件码,但不改变操作数 b 的值。

test 指令用于测试两个操作数 a 和 b。其执行过程如下:

  1. 计算 b & a(与 and 指令相同)。
  2. 根据结果设置条件码(仅设置 SF 和 ZF),但不改变操作数 b 的值。

jX Instructions跳转指令

终于来到je了!je其实是jX中的一种,其实就是根据前面cmp或者test等指令的结果,进行下一步操作。jX指令通常用于实现条件分支、循环等控制结构。例如:

  1. je:当零标志(ZF)设置时跳转。
  2. jne:当零标志(ZF)未设置时跳转。
  3. jg:当有符号数比较结果大于时跳转。
  4. jl:当有符号数比较结果小于时跳转。

setX指令

setX和jX的逻辑就很像了。SetX 指令允许根据条件码的组合来设置目标寄存器的低字节(低 8 位)为 0 或 1。SetX 指令不会改变目标寄存器的其余字节。例如:

  1. sete:当零标志(ZF)设置时,将目标寄存器的低字节设置为 1,否则设置为 0。
  2. setne:当零标志(ZF)未设置时,将目标寄存器的低字节设置为 1,否则设置为 0。
  3. setg:当有符号数比较结果大于时,将目标寄存器的低字节设置为 1,否则设置为 0。
  4. setl:当有符号数比较结果小于时,将目标寄存器的低字节设置为 1,否则设置为 0。

比如假设我们要比较两个整数(存储在寄存器 %rax 和 %rbx 中)是否相等,并将结果存储在寄存器 %rcx 的低字节中(即 1 表示相等,0 表示不相等)。就可以这样:

cmp %rax, %rbx   ; 比较 %rax 和 %rbx 的值
sete %cl         ; 如果它们相等(即零标志 ZF 设置),则将 %rcx 的低字节(%cl)设置为 1,否则设置为 0

稍微有点不同的是setX后面要多个参数,比如目标寄存器(如 %cl 和 %bl)。setX的参数永远是这些低位寄存器(%al, %r8b, etc.)。低位寄存器我们之前提到过,其实就是正常寄存器中的低位部分自己的名字。比如%al其实就是寄存器%rax的最后一个字节。%eax其实就是%rax的后4个字节。寄存器位数不同,应用操作命令也要小心,当然也有专门的命令用来匹配不同位数的寄存器,比如movzbl:

movzbl %al, %eax

movzbl 是一个 x86 汇编指令,全称为 "Move with Zero-Extend Byte to Long"。该指令用于将一个字节(8 位)的数据从源操作数移动到目的操作数,并将其零扩展为长字(32 位)或四字(64 位,取决于操作数的大小)。

好了跑题了,回归正轨。

一个条件判断代码块的有趣例子:

long absdiff (long x, long y) {
    long result;
    if (x > y)
        result = x-y;
    else
        result = y-x;
    return result;
}

machine code:

absdiff:
    movq %rdi, %rax # x
    subq %rsi, %rax # result = x-y
    movq %rsi, %rdx
    subq %rdi, %rdx # eval = y-x
    cmpq %rsi, %rdi # x:y
    cmovle %rdx, %rax # if <=, result = eval
    ret

乍一看好像有点奇怪,怎么没有先cmp x y 然后根据结果jump呢?咋一个jump都没有。这是因为这里使用了条件移动指令Conditional Move Instructions,提前计算好了两种情况下的值,然后用cmovle来完成了同样需求。条件移动指令的主要优势在于它们不会破坏指令流中的顺序执行。在现代处理器的流水线架构中,分支指令(如跳转)可能会导致流水线中的指令顺序中断,从而降低性能。条件移动指令不需要控制转移,因此在处理器流水线中更高效。至于movle中的le是啥意思,就不用多说了吧,和上面jX,setX都一样。

当然条件移动指令并非在所有情况下都是最佳选择。条件移动指令要求在执行之前计算出两个值。这意味着如果计算成本较高,条件移动指令可能并不是最佳选择;再比如计算存在风险或者计算会对修改全局变量等。以下是一些不适合条件移动指令的代码示例。

val = Test(x) ? Hard1(x) : Hard2(x); //计算量大
val = p ? *p : 0; //风险计算
val = Test(x) ? FunctionWithSideEffect1(x) : FunctionWithSideEffect2(x); //造成不必要的执行

switch语句和循环Loop

最后再讲一下switch和loop循环。下面是一个switch语句例子:

long switch_eg(long x, long y, long z)
{
    long w = 1;
    switch(x) {
        // case statements...
    }
    return w;
}

machine code如下:

switch_eg:
    movq %rdx, %rcx
    cmpq $6, %rdi
    ja .L8
    jmp *.L4(,%rdi,8)

在上面的汇编代码中,我们可以看到两种跳转指令:直接跳转ja .L8和间接跳转jmp

 *.L4(,%rdi,8)。直接跳转我们已经很熟悉了,间接跳转就是机器对于switch语句中不同代码块的地址生成的一个jump table,这些代码块的地址往往是连起来的,通过从一个起始位置加偏移的方式去跳转。比如在这类,这个jump table跳转表如下:

.section .rodata
.align 8
.L4:
    .quad .L8
    .quad .L3
    .quad .L5
    .quad .L9
    .quad .L8
    .quad .L7
    .quad .L7

在这个例子中,跳转表的起始地址是.L4。由于表中的每个地址都需要8字节,我们需要将x(存储在%rdi中)乘以8来获取正确的偏移量。然后,从.L4开始,加上偏移量x*8,得到实际的跳转目标。

switch_eg函数中,间接跳转用于根据x的值选择相应的case分支。间接跳转仅在0 ≤ x ≤ 6的范围内有效,因为跳转表.L4仅包含7个目标地址(对应x取值为0到6的情况)。对于x大于6的情况,程序会执行默认分支,即直接跳转到.L8(对应 ja .L8)

当然,至于为什么L8对应x=0,L3对应x=1之类的,可以根据L8的machine code和原代码比较得出。。

Loops循环

循环在c语言中的写法有很多种,但不管是while-do,do-while,for等,转换成machine code后都是差不多的。因为不管是哪种循环,都是具有“init”初始化,“条件”,“主体”,“更新”那么几部分,同样的一种逻辑你用for,while,甚至是goto语句写,出来的machine code估计都是一样的。不再细写~

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

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

相关文章

Synchronized锁

概览 锁的实现基于对象头重的MarkWord&#xff0c;分为 无锁 -> 偏向锁 -> 轻量锁 -> 重量锁 四个状态 状态转换 锁的获取与释放 模型&#xff1a; Markword&#xff1a;指向Monitor的指针Monitor&#xff1a;_cxq&#xff0c;_EntryList,_WaitSet,owner,_recurs…

提高透明LED屏幕显示效果设计指南

设计透明LED屏幕时&#xff0c;可以考虑以下几个因素来提高显示效果&#xff1a; 透明度和亮度&#xff1a;透明LED屏幕的设计目标是实现高透明度和足够的亮度。透明度取决于使用的材料和LED的布局方式。选择高透明度的材料&#xff0c;并确保LED的亮度足够高&#xff0c;以确保…

写给毕业季的学生们|我的五次 offer 选择经历

最近临近毕业季&#xff0c;群里有好多朋友在问面试和 offer 选择的问题&#xff0c;我分享下我过往的相关经历&#xff0c;希望能给各位朋友有所启发。 我是谁&#xff1f; 大家好&#xff0c;我是拭心&#xff0c;内蒙古人&#xff0c;16 年本科毕业于西安电子科技大学&#…

AWTK学习笔记

编译&#xff1a;scons 运行&#xff1a;.\bin\demo.exe xml文件存放在工程的design\default\ui文件夹内 c文件存放在工程的src文件夹内 如果代码没有指定修改&#xff0c;默认按照AWTK Designer设置的控件属性动作运行 API函数查看使用说明&#xff1a;https://awtk.zlg.cn/ap…

Pytorch ----注意力机制与自注意力机制的代码详解与使用

注意力机制的核心重点就是让网络关注到它更需要关注的地方 。 当我们使用卷积神经网络去处理图片的时候&#xff0c; 我们会更希望卷积神经网络去注意应该注意的地方&#xff0c;而不是什么都关注 &#xff0c;我们不可能手动去调节需要注意的地方&#xff0c;这个时候&#x…

centos 7.9离线下载安装vscode,以及插件安装下载

文章目录 一、软件的下载1.采取的方法2.下载相应压缩包3.安装过程4.相关知识 二、插件的安装和下载1.查看vscode的版本号2.查找插件的版本号3.安装vscode插件 三、vscode以及依赖安装包&#xff0c;常用插件百度云&#xff1a; 一、软件的下载 1.采取的方法 从一台联网的cento…

SpringBoot2概览-开发实用篇

知识点 热部署 概念&#xff1a;项目刚启动时需要完成重启重载&#xff0c;而热部署只要重启即可(即仅加载当前开发者自定义开发的资源&#xff0c;不加载jar资源) 重启&#xff1a;加载自定义开发代码&#xff0c;包含类、页面、配置文件等&#xff0c;加载位置在restart类加载…

springboot项目如何将配置文件外挂

为什么要将配置文件外挂 因为springboot项目一般打出来的是jar包&#xff0c;如果要对里面的配置做修改&#xff0c;会比较麻烦&#xff0c;所以需要将配置文件外挂&#xff0c;方便操作哦 怎么做呢 我们先看一个常见的springboot项目的配置文件结构&#xff1a; 分为四个配…

InnoDB的三种行锁(提供具体sql执行案例分析)

InnoDB存储引擎有3种行锁的算法&#xff0c;其分别是&#xff1a; Record Lock&#xff08;记录锁&#xff09;&#xff1a;单个行记录上的范围 (锁住某一行记录)Gap Lock&#xff08;间隙锁&#xff09;&#xff1a;间隙锁&#xff0c;锁定一个范围&#xff0c;但不包含记录本…

十大公认音质好的骨传导耳机,几款音质排行靠前的骨传导耳机

骨传导耳机是通过头部骨迷路传递声音&#xff0c;而不是直接通过耳膜的振动来传递声音。与传统的入耳式耳机相比&#xff0c;骨传导耳机不会堵耳朵&#xff0c;在跑步、骑车等运动时可以更好的接收外界环境音&#xff0c;保护听力&#xff0c;提升安全性。此外&#xff0c;骨传…

Canvas基本使用

1.canvas基本使用 1.1.说明&#xff1a; canvas是双标签,h5中新增的属性默认宽高为300*150浏览器默认canvas展示的是一张图片给canvas添加文字内容是没有任何意义的canvas画布&#xff1a;绘制图形&#xff0c;显示一个文字&#xff0c;必须通过js操作 不要通过样式去设置画…

15.OCR

15.1 OCR流水线及七工作原理 Photo OCR&#xff1a;照片 光学字符识别(photo optical character recognition) Photo OCR注重的问题&#xff1a;如何让计算机都出图片中的文字信息&#xff0c;它有以下步骤&#xff1a; 首先给定某张图片&#xff0c;它将图像扫描一遍&#…

基于小程序的用户服务技术研究

目录 1. 小程序开发技术原理 2. 用户服务设计3. 数据库设计和管理4. 安全和隐私保护5. 性能优化和测试总结 关于基于小程序的用户服务技术研究&#xff0c;这是一个非常广泛和复杂的领域&#xff0c;需要涉及多个方面的知识和技术。一般来说&#xff0c;基于小程序的用户服务技…

零基础想入门网安行业,看这一篇就够了!!!

由于我之前写了不少网络安全技术相关的故事文章&#xff0c;不少读者朋友知道我是从事网络安全相关的工作&#xff0c;于是经常有人在微信里问我&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#xff1f;有哪些方向&#xff1f;怎么选&#xff…

跟着AIGC学Linux:简介(一)

文章目录 1.Linux内核的历史2.基本概念3.发行版4.Linux应用领域5.Linux VS Windows横向对比表格&#xff1a; 1.Linux内核的历史 Linux内核最初由一位名叫Linus Torvalds的芬兰计算机科学家于1991年创建。当时&#xff0c;Torvalds是一名赫尔辛基大学的学生&#xff0c;他在寻…

ROS:话题通信机制详解

目录 ROS&#xff1a;通信机制一、话题通信简介二、话题通信实操&#xff08;C&#xff09;2.1分析2.2发布方代码2.3订阅方代码2.4配置CMakeLists.txt2.5执行2.6注意 三、话题通信实操&#xff08;python&#xff09;3.1分析3.2发布方代码3.3订阅方代码3.4添加可执行权限3.5配置…

Apache Log4j2 漏洞原理

Apache Log4j 远程代码执行漏洞 1.漏洞危害 Apache Log4j被发现存在一处任意代码执行漏洞&#xff0c;由于Apache Log4j2某些功能存在递归解析功能&#xff0c;攻击者可直接构造恶意请求&#xff0c;触发远程代码执行漏洞。经验证&#xff0c;Apache Struts2、Apache Solr、Ap…

Win10控制面板在哪里打开?Win10控制面板打开方式介绍

Win10控制面板在哪里打开&#xff1f;当前很多用户都在使用Win10系统&#xff0c;一些新手用户不清楚在哪里才能打开Win10系统的控制面板&#xff0c;以下给大家介绍三种方式&#xff0c;帮助用户们轻松快速打开Win10控制面板&#xff0c;打开控制面板后用户即可展开不同的设置…

5-1图像信息提取适当剪掉像素点(matlab程序)

代码及运行结果 clear ; close all; gr imread(cameraman.tif); subplot(1,3,1); imshow(gr); subplot(1,3,2); D dct2(gr); F log(abs(D)); imshow(F,[]); subplot(1,3,3); D(abs(D)<200) 0; %会丢掉很多点 &#xff0c;但是原图还可识别&#xff0c;适合做信息提取 M …

这所院校很保护一志愿,学硕爆冷,全部录取,专硕初试第三竟主动放弃录取!

一、学校及专业介绍 广州大学&#xff08;Guangzhou University&#xff09;&#xff0c;简称广大&#xff08;GU&#xff09;&#xff0c;是由广东省广州市人民政府举办的全日制普通高等学校&#xff0c;实行省市共建、以市为主的办学体制&#xff0c;是国家“111计划”建设高…