0
点赞
收藏
分享

微信扫一扫

(第18章)LinuxC本质中x86汇编程序基础


文章目录

  • ​​能看懂基本的汇编程序而不要求会写汇编程序​​
  • ​​一、最简单的汇编程序​​
  • ​​1.代码:结果相当于在C程序的 main 函数中 return 4​​
  • ​​(1)如何运行汇编程序?​​
  • ​​(2)链接的作用:地址重定位,多文件合并成一个可执行文件​​
  • ​​(3)Shell中可以用特殊变量 $? 得到上一条命令的退出状态​​
  • ​​(4)分析汇编程序​​
  • ​​(h)int $0x80​​
  • ​​CPU处于用户模式是不能调用内核函数的​​
  • ​​2.x86汇编的两种语法:intel语法和AT&T语法​​
  • ​​3.习题​​
  • ​​二、x86上重要的寄存器​​
  • ​​1.x86通用寄存器:eab,ebx等​​
  • ​​2.x86特殊寄存器:eip等​​
  • ​​三、第二个汇编程序​​
  • ​​1.求一组数的最大值的汇编程序​​
  • ​​(1)汇编程序的运行​​
  • ​​(2).section .data段​​
  • ​​(3)edi、ebx、eax寄存器的作用​​
  • ​​(4)movl指令​​
  • ​​(5)循环start_loop、比较cmpl、条件je指令​​
  • ​​(6)比较cmpl、条件jle指令​​
  • ​​四、x86的常用寻址方式​​
  • ​​1.内存寻址的通用格式​​
  • ​​2.常用的寻址方式​​
  • ​​五、ELF文件——以第二个汇编程序为基础​​
  • ​​1.UNIX系统的可执行文件都采用ELF格式,类型有三种​​
  • ​​2.汇编程序的汇编、链接、运行过程如下​​
  • ​​3.图示ELF文件​​
  • ​​(1)从链接器的角度看ELF文件​​
  • ​​(2)从加载器的角度看ELF文件​​
  • ​​(3)目标文件、可执行文件、共享库与section header table,program header table的关系​​
  • ​​4.目标文件的符号表(XXX.o文件)​​
  • ​​(1)读目标文件:readelf -a xxx.o​​
  • ​​(a).txt段的作用​​
  • ​​(2)打印目标文件的字节:hexdump -C xxx.o​​
  • ​​(a)C语言全局变量属于.bss段​​
  • ​​(b).bss段和.data段的区别​​
  • ​​(3)机器指令反汇编来分析.txt段:objdump -d xxx.o​​
  • ​​5.可执行文件的符号表:XXX​​
  • ​​(1)读可执行文件:readelf -a xxx​​
  • ​​(d)文件和加载地址的对应关系​​
  • ​​(2)机器指令反汇编来分析.txt段:objdump -d xxx​​

能看懂基本的汇编程序而不要求会写汇编程序

一、最简单的汇编程序

1.代码:结果相当于在C程序的 main 函数中 return 4

(第18章)LinuxC本质中x86汇编程序基础_目标文件

(1)如何运行汇编程序?

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_02

(2)链接的作用:地址重定位,多文件合并成一个可执行文件

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_03

(3)Shell中可以用特殊变量 $? 得到上一条命令的退出状态

现在执行这个程序,它只做了一件事就是退出,退出状态是4

(第18章)LinuxC本质中x86汇编程序基础_目标文件_04

(4)分析汇编程序

(a)首先, # 号表示单行注释;

(b)伪操作
汇编程序中以 . 开头的名称并不是指令的助记符,不会被翻译成机器指令,而是给汇编器一些特殊指示,称为汇编指示(Assembler Directive) 或伪操作(Pseudo-operation) ,由于它不是真正的指令所以加个“伪”字。

(c).section .data
.section 指示把代码划分成若干个段(Section) ,程序被操作系统加载执行时,每个段被加载到不同的地址, 操作系统对不同的页面设置不同的读、写、执行权限。
.data 段保存程序的数据,是可读可写的,相当于C程序的全局变量。

(d).section .text
.text 段保存代码,是只读和可执行的,后面那些指令都属于 .text 段。

(e).globl _start

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_05


(f)_start:

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_06


(g)movl $1, %eax

(第18章)LinuxC本质中x86汇编程序基础_加载_07

(h)int $0x80
CPU处于用户模式是不能调用内核函数的

(第18章)LinuxC本质中x86汇编程序基础_加载_08

2.x86汇编的两种语法:intel语法和AT&T语法

UNIX平台的书都采用AT&T语法

3.习题

(第18章)LinuxC本质中x86汇编程序基础_目标文件_09


(第18章)LinuxC本质中x86汇编程序基础_加载_10

二、x86上重要的寄存器

1.x86通用寄存器:eab,ebx等

(第18章)LinuxC本质中x86汇编程序基础_目标文件_11

2.x86特殊寄存器:eip等

(第18章)LinuxC本质中x86汇编程序基础_目标文件_12

三、第二个汇编程序

1.求一组数的最大值的汇编程序

(第18章)LinuxC本质中x86汇编程序基础_加载_13

(1)汇编程序的运行

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_14

(2).section .data段

(第18章)LinuxC本质中x86汇编程序基础_目标文件_15


补充说明:

(a)这组数在 .data 段给出;

(b).long 指示声明一组数,每个数占32位,相当于C语言中的数组;

(c)汇编器会把数组的首地址作为 data_items 符号所代表的地址, data_items 类似于C语言中的数组名; data_items 这个标号没有用 .globl 声明,因为它只在这个汇编程序内部使用,链接器不需要用到这个名字;

(d)除了 .long 之外,常用的数据声明还有:

(第18章)LinuxC本质中x86汇编程序基础_目标文件_16

(3)edi、ebx、eax寄存器的作用

(第18章)LinuxC本质中x86汇编程序基础_目标文件_17

(4)movl指令

(第18章)LinuxC本质中x86汇编程序基础_目标文件_18

(5)循环start_loop、比较cmpl、条件je指令

(第18章)LinuxC本质中x86汇编程序基础_加载_19


(第18章)LinuxC本质中x86汇编程序基础_汇编程序_20

(6)比较cmpl、条件jle指令

(第18章)LinuxC本质中x86汇编程序基础_加载_21

四、x86的常用寻址方式

1.内存寻址的通用格式

(第18章)LinuxC本质中x86汇编程序基础_加载_22

2.常用的寻址方式

(第18章)LinuxC本质中x86汇编程序基础_目标文件_23


(第18章)LinuxC本质中x86汇编程序基础_加载_24

五、ELF文件——以第二个汇编程序为基础

1.UNIX系统的可执行文件都采用ELF格式,类型有三种

(第18章)LinuxC本质中x86汇编程序基础_目标文件_25

2.汇编程序的汇编、链接、运行过程如下

(第18章)LinuxC本质中x86汇编程序基础_目标文件_26

3.图示ELF文件

(第18章)LinuxC本质中x86汇编程序基础_加载_27


注:注意Section Header Table和Program Header Table并不是一定要位于文件的开头和结尾,其位置由ELF Header指出,上图这么画只是为了清晰。

(1)从链接器的角度看ELF文件

(第18章)LinuxC本质中x86汇编程序基础_加载_28

(2)从加载器的角度看ELF文件

(a)右边是从加载器的视角来看ELF文件,开头是ELF Header,Program Header Table中保存了所有Segment的描述信息,Section Header Table在加载过程中用不到, 所以是可有可无的。
(b)从上图可以看出,一个Segment由一个或多个Section组成。
(c)这些Section加载到内存时具有相同的访问权限。
(d)有些Section只对链接器有意义,在运行时用不到,也不需要加载到内存,那么就不属于任何Segment。

(3)目标文件、可执行文件、共享库与section header table,program header table的关系

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_29

4.目标文件的符号表(XXX.o文件)

(1)读目标文件:readelf -a xxx.o

(a)用 readelf 工具读出目标文件 max.o 的ELF Header和Section Header Table。

(b)ELF Header中描述了操作系统是UNIX,体系结构是80386。

(c)文件地址的定义:文件开头第一个字节的地址是0,然后每个字节占一个地址。

(第18章)LinuxC本质中x86汇编程序基础_加载_30


(第18章)LinuxC本质中x86汇编程序基础_目标文件_31


(第18章)LinuxC本质中x86汇编程序基础_目标文件_32


补充:

(a)off和size的eg如下

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_33

readelf 输出的最后一部分

(第18章)LinuxC本质中x86汇编程序基础_加载_34


说明:

(a).txt段的作用

.rel.text 告诉链接器指令中的哪些地方需要做重定位

(b)

(第18章)LinuxC本质中x86汇编程序基础_加载_35

(2)打印目标文件的字节:hexdump -C xxx.o

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_36


说明:

(a)C语言全局变量属于.bss段

C语言的全局变量如果在代码中没有初始化,就会在程序加载时用0初始化。这种数据属于 .bss 段。

(b).bss段和.data段的区别

  • 在加载时, .bss 段和 .data 段一样都是可读可写的数据。
  • 但是在ELF文件中 .data 段需要占用一部分空间保存初始值,而 .bss 段则不需要。
    -why?
    .bss 段在文件中只占一个Section Header而没有对应的Section,程序加载时 .bss 段占多大内存空间在Section Header中描述。

(3)机器指令反汇编来分析.txt段:objdump -d xxx.o

目前所有指令中用到的符号地址都是相对地址, 下一步链接器要修改这些指令,把其中的地址都改成加载时的内存地址,这些指令才能正确执行。

(第18章)LinuxC本质中x86汇编程序基础_加载_37

5.可执行文件的符号表:XXX

(1)读可执行文件:readelf -a xxx

(第18章)LinuxC本质中x86汇编程序基础_加载_38


(第18章)LinuxC本质中x86汇编程序基础_加载_39


(a)相比较于readelf -a 目标文件.o,多了两个Program Header,少了两个Section Header。

(b)在Section Header Table中(就是Section Headerts),bss 段没有用到,所以被删掉了。 .rel.text 段就是用于链接过程的,做完链接就没用了,所以也删掉了。

(c)在Program Header Table中,Flg 列指出第一个Segment的访问权限是可读可执行,第二个Segment的访问权限是可读可写。

(d)文件和加载地址的对应关系

最后一列 Align 的值0x1000(4K) 是x86平台的内存页面大小。在加载时文件也要按内存页面大小分成若干页,文件中的一页对应内存中的一页, 对应关系如下图所示。

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_40

(2)机器指令反汇编来分析.txt段:objdump -d xxx

(第18章)LinuxC本质中x86汇编程序基础_目标文件_41


解释说明如下:

(a)指令中的相对地址都改成绝对地址了。

首先看跳转指令, 原来目标文件的指令是这样:

(第18章)LinuxC本质中x86汇编程序基础_加载_42


(b)再看内存访问指令,原来目标文件的指令是这样:

(第18章)LinuxC本质中x86汇编程序基础_汇编程序_43


举报

相关推荐

0 条评论