在实际工作中接触到一些与x86/x64平台底层的问题时,往往是遇到不懂的就翻翻Intel或AMD提供的手册,这样掌握并不牢固,下次重遇问题时还要翻手册。现在让我们一起来系统地学习x86/x64体系知识,然后需要温故而知新。

实验的重要性

在学习过程中,我们以探索为目的,以实验为依托。要透彻地对一个知识点进行理解,显然经过测试实验的论证是最好的方法,也只有经过全方位的测试才是最为真实可靠的。Intel和AMD官方手册某些描述上存在着隐晦难懂的地方,甚至可能还会出现错误。因此测试实验起的作用是:验证真伪和去除疑惑。

下图是在Intel64软件开发者手册里截取到的一段有误的描述:

截图中描述的是INT指令在返回时的一部分处理流程:在IA-32e模式下(描述中包括了64位模式和compatibility模式)当operand size为32或16时,只会pop出32位或16位的CS,EIP以及EFLAGS值。然而实际上在64位模式下,处理器还会无条件pop出SS和ESP值并不依赖于operandsize的值。

这个描述与x64体系中的设计产生一些冲突(主要依据于AMD64手册的描述)。因此,在无法准确判断时,我们做出测试实验来验证,在64位模式下执行下面的代码:

mov WORD [rsp], 0

mov WORD [rsp + 2], KERNEL_CS

mov WORD [rsp + 4], 46

mov WORD [rsp + 6], 08F0h

mov WORD [rsp + 8], 0A0h

db 66h

iret

这段代码执行16位的中断返回,在栈中压入的是16位的值,实验的结果是:

这是运行在bochs上的测试结果,RSP和SS值没有改变,没有pop出SS与SP值,这是bochs按照Intel64手册上所描述的流程进行模拟了。

在vmware和真实机器上执行显示出SS值为0A0h,RSP值为08F0h,处理器已经从栈中POP出SS与SP值。

然这个实验可以写得更好些更清晰些,显然从这个实验测试里知道Intel64手册中的这一段描述与事实不符。这里阐述了实验作用之一:就是验证真伪。

下面一段话是关于中断优先级别的描述:

“Each interrupt vector is an 8-bitvalue. The interrupt-priority class is the value of bits 7:4 of theinterrupt vector. The lowest interrupt-priority class is 1 and the highest is15; interrupts with vectors in the range 0–15 (with interrupt-priority class 0)are illegal and are never delivered. Because vectors 0–31 are reserved fordedicated uses by

the Intel 64 and IA-32 architectures, software should configure interruptvectors to use interrupt-priority classes in the range 2–15.

Each interrupt-priority class encompasses 16 vectors. The relativepriority of interrupts within an interrupt-priority class is determined by thevalue of bits 3:0 of the vector number. The higher the value of those bits, thehigher the priority within that interrupt-priority class. Thus, each interruptvector comprises two parts, with the high 4 bits indicating itsinterrupt-priority class and the low 4 bits indicating its ranking within theinterrupt-priority class.”

这段话描述8位的中断vector被分为两部分用来管理优先级,高4位是priorityclass,低4位是priority ranking。我们可以看作:高4位管理等级,低4位是等级内的排名。vector值大优先级别就高。

然而这里的描述会让我们产生困惑:同一个class内的ranking是否越大优先级别越高,实际上不是,处理器响应中断请求是按vector[7:4]值来仲裁:只有priority class大的才能响应。

上图所显示的是另一个测试实验,当我们对TPR(Task Priority Register)设置的值为0x32时,它的中断门坎的priority class值为3(第3级),同时PPR(Processor Priority Register)也被置为0x32,PPR的值受TPR与ISR影响。只有满足下列条件时中断请求才能被响应:

vector[7:4] > PPR[7:4]

因此:vector为0x33的中断请求发生时,将会被阻塞得不到响应的,只有vector的priority class值大于3时才会响应。

然而,Intel64手册里描述的并不清晰,我们只能通过实验来测试和验证,去除我们的困惑,这是实验的第二个作用。

构造实验平台

我们可以想象到:由于OS的限制,大多数实验是并不适合在现有的OS平台里进行测试。因此我们需要选择要祼机上进行测试。

可以选择的运行环境有真实机器,bochs模拟器或者vmware虚拟机。那么我们可以选择的介质是U盘,硬盘映像文件或者软盘映像文件,并需要编写自己的boot程序来引导测试实验。根据不同的介质软件不同的格式:U盘和硬盘映像文件使用FAT32格式,软件映像文件可以直接将boot代码写入MBR中即可。

上面是启动boot程序的流程,FAT32文件格式中,我们的boot程序写入63号扇区(从0开始),BIOS将boot程序读入7C00h位置后,继续加载我们实验的后续模式。

以U盘和硬盘映像文件使用的FAT32文件格式为例,下面的映像文件组织:

我们实验中常用的模块是boot模块,setup模块,lib16模块,protected模块,lib32模块以及long模块。lib16与lib32模块是库代码,protected模块是32位保护模式执行代码,long模块是64位long模块执行代码,而boot模块引导它们,setup模块切入保护模式。

规定了这些模块在映像文件中的存放位置后,需要将这些模块代码写入映像文件中,可以使用最原始的方法,即:手工使用Hex类型软件合并写入。这种方法实在是太麻烦了。

这里使用自己编写的合并工具merge,根据它的配置文件批量写入到映像文件中,下面是配置文件的示例:

# 输入文件, 输入文件 offset, 输出文件, 输出文件 offset, 写入 block 数( 1 block = 512bytes)

#**** 每一项用逗号分隔 ****

#

#example:

#

#模块名 offset 输出文件名 offset count(1count = 512 bytes)

#-------------------------------------------------

#boot, 0, demo.img, 0, 1

#setup, 0, demo.img, 1, 2

#init, 0, demo.img, 3, 5

#

# 意思是:

#boot 模块从 block 0 开始写入 demo.img 写入位置为 block 0, 写入 1 个 block

#setup 模块从 block 0 开始写入 demo.img 写入位置为 block 1, 写入 2 个 block

#init 模块从 block 0 开始写入 demo.img 写入位置为 block 3, 写入 5 个 block

# 下面是第2 章中使用到的配置实例:

boot,0,demo.img,0,1

每一行有5个项目,以逗号分隔。分别是:源文件,源文件起始点,目标文件,目标文件起始点,写入的块数(以512字节为一块)。使用merge工具我们只需要在命令执行merge命令即可。merge会帮助我们批量地写入目标文件相应的位置,省事且不会出错。

这里,\\.\g就是U盘的设备名,当配置文件中添加写入U盘时(目标文件为U盘设备名),我们可以插入U盘到真实机器去运行。

接下来,需要编写自己的boot代码,下面是简短的示例片断:

; set BOOT_SEG environment

mov ax, cs

mov ds, ax

mov ss, ax

mov es, ax

mov sp, BOOT_SEG                ; 设 stack 底为 BOOT_SEG

call clear_screen

mov si, hello

call print_message

mov si, 20                  ; setup 模块在第20 号扇区里

mov di, SETUP_SEG - 2

call load_module                ; 使用 load_module() 读多个扇区

mov si, SETUP_SEG

call print_message

mov si, word [load_message_table + eax * 2]

call print_message

next:

jmp $

在这个boot示例里,主要的工作是调用load_module()函数来加载上述的某个模块,接下来,调用print_message()打印信息。

最后,每个测试实验下,都包括源代码文件,bochs配置文件,merge工具的配置文件,软盘映像文件(demo.img)以及硬盘映像文件(c.img)。

一起学习x86/x64知识相关推荐

  1. 一起学习x86/x64知识(一)

    在实际工作中接触到一些与x86/x64平台底层的问题时,往往是遇到不懂的就翻翻Intel或AMD提供的手册,这样掌握并不牢固,下次重遇问题时还要翻手册.现在让我们一起来系统地学习x86/x64体系知识 ...

  2. x86_x64 linux模式,一起学习x86/x64知识

    在vmware和真实机器上执行显示出SS值为0A0h,RSP值为08F0h,处理器已经从栈中POP出SS与SP值. 手册中的这一段描述与事实不符.这里阐述了实验作用之一:就是验证真伪. 下面一段话是关 ...

  3. 视频教程-x86/x64软件逆向分析入门-C/C++

    x86/x64软件逆向分析入门 成都理工大学优秀讲师,教授,二十年开发经验,和十六年一线教学工作经验,发表学术论文十余篇.参与包括863项目等多个国家级科研项目,参与包括微信机器人(WeChaty)等 ...

  4. 《x86/x64体系探索及编程》图书信息

    x86/x64体系探索及编程 (对x86处理器介绍得最详尽又最具实践指导意义的一本书) 邓志著 ISBN 978-7-121-18176-4 2012年10月出版 定价:119.00元 16开 840 ...

  5. 关于.NET编译的目标平台(AnyCPU,x86,x64)

    在VisualStudio中项目平台属性包含x86/x64/AnyCPU三个选项,之前的项目中并没有特别去关注这一点,最近的项目中涉及到了在不同平台运行的问题,所以专门了解并整理了这方面的知识. x8 ...

  6. DipTrace 4.1.0 x86 / x64原理图捕获软件

    DipTrace 4.1.0 x86 / x64原理图捕获软件 DipTrace软件是一种原理图捕获软件,可以提供用于设计从原理图到文件的简单或复杂多层板的高质量PCB设计. DipTrace 4.1 ...

  7. 零基础该如何学习Web前端知识?

    想要跳槽到IT行业人在近几年越来越多,大部分都是想要学习web前端技术,但是这其中有很多都是零基础学员,大家都想知道零基础该如何学习Web前端知识?我们来看看下面的详细介绍. 零基础该如何学习Web前 ...

  8. 转载 干货 | 陪伴我学习NLP、知识图谱的那些资源(教程+书籍+网站+工具+论文...可以说很全面了)

    https://blog.csdn.net/guleileo/article/details/81140179 干货 | 陪伴我学习NLP.知识图谱的那些资源(教程+书籍+网站+工具+论文...可以说 ...

  9. 关于VS项目平台的x86,x64,Any CPU以及Debug和Release

    相信对于很多刚接触打包程序的同志来说,关于x86,x64,Any CPU这三个项目平台,以及解决方案配置Debug和Release有什么区别?这个问题一定有许多的困惑,甚至不乏一些已经工作了很久的老程 ...

  10. 关于.NET编译的目标平台(AnyCPU,x86,x64) (转)

    关于.NET编译的目标平台(AnyCPU,x86,x64)(转) 今天有项目的代码收到客户的反馈,要求所有的EXE工程的目标平台全部指定成x86,而所有DLL工程的目标平台全部指定成AnyCPU . ...

最新文章

  1. Vue源码探究-全局API
  2. php内置函数和扩展,PHP 内置函数strlen 和mbstring扩展函数mb_strlen的区别
  3. Linux驱动之混杂设备(misc)
  4. VTK:模型用法实战
  5. java环境变量path好长_java环境变量设置
  6. bug?VS2010中CImageList::DrawIndirect总是返回失败
  7. c语言随机产生四位数,习题:随机产生N个四位正整数,将其中的素数选出,并升序排列之输…...
  8. 线程安全的Singleton模板
  9. python 在线培训费用-参加线上python培训班要多少钱?
  10. Java如何让程序一直运行,不停止
  11. 网络安全-跨站脚本攻击(XSS)的原理、攻击及防御
  12. 怎样可以促进睡眠质量?睡眠不好一定要知道这些方法
  13. 【线性代数】线性代数的几何意义
  14. 视频数据丢失怎么办 怎样找回丢失的视频数据
  15. 多种方法解决多个div并排显示的问题
  16. 前端学习:浏览器缓存方式有哪些(cookie、localstorage、sessionstorage)
  17. 基于C++和OpenGL (GLUT) 实现太阳系行星系统
  18. linux下写的程序生成.exe在windows下运行
  19. 6.windbg-windbg环境
  20. 安装MySQL卡在apply_安装mysql遇到的坑:在apply server configuration和starting server均被卡...

热门文章

  1. Lodop设置打印维护返回打印语句代码
  2. python_爬虫_模块
  3. 【转】android fragment 博客 学习
  4. Swing 显示良好JPanel保存为图片
  5. C# Win32API
  6. Whl自助搜索下载器
  7. 负载均衡算法及手段(转)
  8. 洛谷 P1278 单词游戏 【状压dp】
  9. 双重释放漏洞(来自漏洞战争一书)
  10. shell中exec命令