2023-03-08  阅读(2)
原文作者:ysocean 原文地址:https://www.cnblogs.com/ysocean

  在进行本章的讲解之前,我们先说明讲解的机器语言型号。上一篇汇编语言和机器语言我们讲过,机器语言是直接面向处理器(Processor:CPU)的程序设计语言,但是每一种这样的微处理器(CPU)由于硬件设计和内部结构的不同,所以每一种微处理器都有自己的机器指令集,也就是机器语言。而汇编语言是便于记忆的机器语言。本系列博客将会介绍两种相关的机器语言:Intel IA32 和 x86-64。前者是当今大多数计算机的主导语言,而后者是在 64 位机器上运行的扩展,我们先从 Intel IA32开始。

1、机器级代码

  前面我们就说过,计算机系统使用了多种不同的抽象,利用更简单的抽象模型来隐藏实现的细节。对于机器级编程来说,有两种抽象特别重要:

  ①、第一种是将机器级程序的格式和行为定义为指令集体系结构(Instruction set architecture ,ISA),它定义了处理器状态、指令的格式,以及每条指令对状态的影响。大多数 ISA,包括 Intel IA32 和 x86-64,将程序的行为描述成好像每条指令是按顺序执行的,即一条指令结束后,下一条指令开始。处理器的硬件远比描述的精细复杂,它们并发的执行许多指令,但是可以采取措施保证整体行为与 ISA 指定的顺序执行完全一致。

  ②、第二种是机器程序使用的存储器地址是虚拟地址,提供的存储器模型看上去是一个非常大的字节数组。存储器系统的实际实现是将多个硬件存储器和操作系统软件组合起来。

  在整个编译过程中,编译器会完成大部分工作,将把用 C 语言提供的相对比较抽象的执行模型表示的程序转化成处理器执行的基本指令,也就是汇编语言,汇编语言在被汇编器转化成机器语言,然后计算机去执行。汇编语言也就是具有更好的可读性的机器语言,所以能够理解汇编代码以及它与原始 C 代码的关系,是理解计算机如何执行程序的关键步骤。

  我们在写 C 程序时,处理器的状态都是隐藏的,即我们编码不用去直接操作处理器。但是在汇编语言中,如下的几个处理器状态是可见的:

  一、程序计数器(在 IA32 中通常称为 PC,用 %eip 表示):指示将要执行的下一条指令在存储器中的地址。

  二、整数寄存器文件:包含8个命名的位置,可以存储一些地址或者整数的数据。有的用来记录某些重要的程序状态,有的则用来保存临时数据。

  三、条件码寄存器:保存最近执行的算数或逻辑指令的状态信息,它们用来实现控制或数据流中的条件变化,比如用来实现 if 和 while 语句。

  四、浮点寄存器:存储浮点数。

   注意:C 语言提供的模型可以在存储器中声明和分配各种数据类型的对象。但是实际上机器代码则只是简单的将存储器看成是一个很大的、按字节寻址的数组。

**  汇编代码不区分有符号或者无符号整数,不区分各种类型的指针。甚至不区分指针和整数。**

2、程序存储器

**  ** 程序存储器包含程序的可执行机器代码,操作系统需要的一些信息,用来管理过程调用和返回的运行时栈,以及用户分配的存储器块。

  程序存储器用虚拟地址来寻址,在任意给定的时刻,只认为有限的一部分虚拟地址是合法的。操作系统则负责管理虚拟地址空间,将虚拟地址翻译成实际处理器存储器(processor memory)中的物理地址。

3、程序示例

  如下这是一段 C 程序代码 hello.c:

    #include <stdio.h>
    
    int main()
    {
    	return sum(1,3);
    }
    int accum = 0;
    int sum(int x,int y)
    {
    	int t= x+y;
    	accum += t;
    	return t;	
    }

  然后执行如下命令生成汇编程序

    gcc -O1 -S hello.c

  -O1是优化选项,少优化->多优化:

  O0 -->> O1 -->> O2 -->> O3

  -O0表示没有优化,-O1为缺省值,-O3优化级别最高

  生成的汇编程序 hello.s

            .file   "hello.c"
            .text
    .globl sum
            .type   sum, @function  //定义全局函数sum
    sum:
    .LFB12:
            .cfi_startproc
            leal    (%rsi,%rdi), %eax //把寄存器%rsi和寄存器%rdi的值的地址装入eax中,即&(rsi+rdi)=eax
            addl    %eax, accum(%rip) //把寄存器%eax和寄存器%rip的值相加,并存放到 %rip中
            ret
            .cfi_endproc
    .LFE12:
            .size   sum, .-sum
    .globl main   //主函数main
            .type   main, @function
    main:
    .LFB11:
            .cfi_startproc
            movl    $3, %esi //将数据3复制到%esi寄存器
            movl    $1, %edi
            movl    $0, %eax
            call    sum  //将 sum 指令的地址压入到栈中,也就是下一条指令执行调用 sum 函数
            rep
            ret
            .cfi_endproc
    .LFE11:
            .size   main, .-main
    .globl accum  //定义全局变量accum
            .bss
            .align 4
            .type   accum, @object
            .size   accum, 4
    accum:
            .zero   4
            .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-18)"
            .section        .note.GNU-stack,"",@progbits

   注意:所有以 ‘.’ 开头的行都是指导汇编器和链接器的命令,我们通常可以忽略这些行。

**  现在这些汇编指令大家可以不用完全理解,后面会详细进行讲解。**

4、数据格式

  由于计算机是由16位体系结构扩展为32位体系结构的,Intel 用术语 “字”(word) 表示16位数据类型,因此 32 位表示 “双字”(double words),64 位数称为“四字”(quad words).

  前面的汇编代码我们可以看到所有的汇编指令都带有字母 l,比如movl、addl、subl、pushl等等,这个l的后缀其实就是表示的数据格式,表示我们操作的是32位的数值。

  下面我们看一下 C 语言基本数据类型对应的 IA32 表示:

202303082202293881.png

  上面的图示很好理解,比如mov指令,它是一个数据传送的指令,那么movb就代表传送一个字节的数据,movw就代表传送两个字节的数据,而movl就代表传送四个字节的数据。需要注意的是,long long int在IA32架构中是不支持这种数据格式的。而且汇编代码使用后缀 “l” 来表示 4 字节整数和8字节双精度浮点数,这不会产生歧义,因为浮点数使用的是一组完全不同的指令和寄存器。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文