前言

        现在我们来阅读邓志老师的《x86/x64体系探索及编程》,边阅读边将其代码放到bochs中运行,然后观察bochs的CPU是如何来模拟的。现在我们来详细分析ex3-2目录里面的内容。

boot.asm 代码解读

自己在工作中经常看汇编代码,但是写汇编代码真的很少写过,我们现在一边分析着这段boot汇编代码一边回顾其如何编写。

; Int 19h 加载 sector 0 (MBR) 进入 BOOT_SEG 段, BOOT_SEG 定义为 0x7c00org BOOT_SEGstart:cli; enable a20 lineFAST_A20_ENABLEsti; set BOOT_SEG environmentmov ax, csmov ds, axmov ss, axmov es, axmov sp, BOOT_SEG                        ; 设 stack 底为 BOOT_SEGcall clear_screenmov si, hellocall print_messagemov si, 20                              ; setup 模块在第20号扇区里mov di, SETUP_SEG - 2call load_module                        ; 使用 load_module() 读多个扇区mov si, SETUP_SEGcall print_messagemov si, word [load_message_table + eax * 2]call print_messagenext:        jmp $

org 解读

The bin format provides an additional directive to the list given in chapter 7: ORG. The function of the ORG directive is to specify the origin address which NASM will assume the program begins at when it is loaded into memory.

For example, the following code will generate the longword 0x00000104:

        org     0x100 dd      label
label:

nasm手册中描述该指令,当程序加载到内存时,其org关键字指定其起始内存。我们看其代码,其在support.inc文件中定义了BOOT_SEG,该程序加载到7c00h处。

        org BOOT_SEGstart:cli# support.inc
BOOT_SEG                equ     7c00h

我们使用前面配置好的IDA调试器来分析一下,果然其定位到7c00h处,我们继续往下分析。

clear_screen函数分析

clear_screen:pushamov ax, 0x0600xor cx, cxxor bh, 0x0f                            ; whitemov dh, 24mov dl, 79int 0x10

如上,现在给你这段汇编代码,你应该如何分析呢?其首先确定调用 int 0x10中断,其次找到ah功能号,这里 mov ax,0x0600,则ah为0x6,我们应该去查阅手册 int 0x10, ah = 6,看手册的内容。(注意,在汇编语言中ah为功能号,单纯中断号范围太小,不能包含全部功能,需要ah作为功能号来进行指令的拓展

如上wiki百科中所描述的,al = 0代表清除,24行79列的全部清除,关于BH颜色的表示,已经说了,BH = 43h时,4-3 - 红-Cay,前面是背景,而后面的是字体颜色,则 "xor bh 0x0f"表示黑底白色字体。

这种查阅比较麻烦,但重要的是你要知道去如何查阅,不必要背过。

汇编中字符串与数组的定义

继续往下读,我们遇到了这个指令“mov si, hello”,其中hello是一个字符串,我们正好来分析一下其是如何来定义的。我们可能学习C语言之后看汇编语言的定义很别扭,其实我们如果从单位的角度来分析,则很好理解,如下:

// 字符串
hello db 'hello, world', 13, 10, 0// dw数组
message_table   dw read_sector_success, read_sector_failure, 0

其遵循 " 命名  单位 xx , xx , ......" 这种规则,首先我们需要确定的是单位, 之后再来使用 ',' 来进行分割,并不需要刻意添加结尾。

在定义单个字符时,可以使用双引号的技巧来定义多个字符,但是其并不会给你后面加0,因此你必须手动添加。不仅是定义字符串,在定义其他数组时为了方便遍历,也需要后面手动添加0.

        其实耐心分析一下,发现这些并不困难,之前每次看这些汇编代码都心气浮躁,看了一遍看似懂了,但转头让自己写,发现自己啥也写不出来。。。

print_message函数分析

        mov si, hellocall print_messageprint_message:pushamov ah, 0x0exor bh, bh        do_print_message_loop:        lodsbtest al,aljz do_print_message_doneint 0x10jmp do_print_message_loopdo_print_message_done:        poparet

代码如下,我们现在有上面分析clear_screen函数的经历,再分析下面这个函数就轻松多了。

lodsb指令将si指针指向的数据加载来al寄存器中,然后指针自动加1.所以 lodsb之后,紧接着"test al,al“判断是否读到指针结尾,然后循环来进行处理。

因此,通过这个我们可以得知,其在汇编模式下没有一条指令可以让你全部输出内容,但是可以使用"lodsb+循环"的方式,连续调用int 0x10来连续输出字符串。

load_module代码解读

SETUP_SEG               equ     8000hmov si, 20                              ; setup ģ���ڵ�20��������mov di, SETUP_SEG - 2call load_module                        ; ʹ�� load_module() ���������load_module:call read_sector                        ; read_sector(sector, buf)test ax, axjnz do_load_module_donemov cx, [di]                            ; ��ȡģ�� sizetest cx, cxsetz aljz do_load_module_doneadd cx, 512 - 1shr cx, 9                               ; ���� block��sectors��do_load_module_loop:  call dotdec cxjz do_load_module_done inc siadd di, 0x200call read_sectortest ax, axjz do_load_module_loopdo_load_module_done:  ret

代码如上,这个代码看了好久才理解。简单来说,我们在构造c.img时,使用的是LBA模式,但是当读取磁盘时,当不支持拓展读时,需要转而使用CHS模式。如果要使用 "int 0x13,ah = 0x2" 这种方式来读取磁盘,需要将LBA转换CHS,运算方法的解释网上有很多。

bochs的bios支持拓展读,可以使用"int 0x13,ah = 0x42",这样仅需要LBA而不需要CHS,下面是使用拓展读时寄存器的详细信息:

上面可以看到,源代码中注释存在一些问题,别在阅读时被误导了。

mov si, word [load_message_table + eax * 2] 汇编分析

这段汇编中,有一个word关键字,这相当于标记这个 load_message_table + eax * 2 内存指针的单位,拿C语言来将 int x = *(int*)0x120421 ,这里的 (int*) 相当于 word 关键字的作用,当然你可以省略掉它,编译器会将si的长度匹配到[load_message_table + eax * 2]中,但是严谨一点,之后涉及内存指针的都要写上。

配置文件

原书中不知道使用的bochs是什么版本的,但是在2.6.11中配置文件早已不可用,下面是我的配置文件,照着之前改一下相对路径就可以用。


romimage: file=D:/code/git_local_code/kkbochs-master/bochs-src/bios/BIOS-bochs-latest cpu: count=1, ips=50000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def"
cpu: cpuid_limit_winnt=0memory: guest=512, host=256vgaromimage: file=D:/code/git_local_code/kkbochs-master/bochs-src/bios/VGABIOS-lgpl-latestfloppya: 1_44=/dev/fd0, status=insertedata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9floppya: 1_44=demo.img, status=inserted
ata0-master: type=disk, path="c.img", mode=flat, cylinders=2, heads=16, spt=63#boot: floppy
boot: diskfloppy_bootsig_check: disabled=0#log: /dev/null
#log: bochsout.txt#panic: action=ask
#error: action=report
info: action=report
#debug: action=ignore
#debug: action=report#debugger_log: /dev/null
#debugger_log: debugger.out
#debugger_log: debugger.outparport1: enabled=1, file="parport.out"# keyboard_serial_delay: 250# keyboard_paste_delay: 100000mouse: enabled=0private_colormap: enabled=0# keyboard_mapping: enabled=0, map=pci: enabled=1, chipset=i440fx#megs: 256
#megs: 128
#megs: 64
#megs: 32
#megs: 16
#megs: 8

总结

这篇文章简单介绍了一下ext3-2/boot.asm中汇编的相关信息,下面我们尝试通过调试汇编代码来探究bochs的CPU是如何实现它们的。

Bochs源码分析 - 11:《X86探索及编程》代码初步解释相关推荐

  1. Bochs源码分析 - 16:conforming与non-conforming代码段区别以及Bochs代码的实现

    前言 之前在学习x86架构时,在代码段中有一个点让我感到困惑,就是type field 11位.这个之前一直似懂非懂,说不理解吧知道这么个玩意,说理解吧又不知道其具体干嘛,感觉是方便系统调用加快速度, ...

  2. 04特性源码分析-ReentrantReadWriteLock原理-AQS-并发编程(Java)

    文章目录 1 锁重入 2 锁重入计数 2.1 读锁加锁计数 2.2 读锁解锁计数 3 公平与非公平锁 3.1 非公平锁 3.2 公平锁 4 锁降级与锁升级 4.1 锁升级 4.2 锁降级 5 full ...

  3. 【Android SDM660源码分析】- 04 - UEFI ABL LinuxLoader 代码分析

    [Android SDM660源码分析]- 04 - UEFI ABL LinuxLoader 代码分析 1. LinuxLoader.c 系列文章: <[Android SDM660开机流程] ...

  4. Bochs源码分析 - 20: 开启保护模式

    前言 在邓志老师的<x86/x64体系探索及编程>中讲述了开启保护模式的顺序,我尝试着翻阅intel手册,但很遗憾似乎自己没有找到对此的描述(应该是有的,但是自己没找到,日后找到了会补充上 ...

  5. Bochs源码分析 - 6: bochs的物理内存初始化

    前言 上一篇文章,我们走马观花地介绍了bochs从启动到CPU执行流程的大体流程,里面相关数据结构没详细分析.这篇文章我们尝试来详细分析一下bochs的物理内存初始化,首先有个概念需要理清(相信来看b ...

  6. 4hutool源码分析:DateUtil(时间工具类)-格式化时间(万字长文源码分析,学大佬如何写代码)

    技术活,该赏 点赞再看,养成习惯 看本篇文章前,建议先对java源码的日期和时间有一定的了解,如果不了解的话,可以先看这篇文章: 万字博文教你搞懂java源码的日期和时间相关用法 关联文章: huto ...

  7. Bochs源码分析 - 28:bochs开启x2apic与SMP编译说明

    前言 我们现在来根据<x86/x64体系探索及编程>的第十七章分析apic结构,第一个实验就是检测local apic与x2apic,但是现在bochs最新版本配置文件有些变动,需要添加有 ...

  8. Bochs源码分析 - 14:bochs关于实地址模式下IVT表的管理

    前言 这篇文章对应着邓志老师的<x86/x64体系探索及编程>的第八章,讲述的是实模式,实模式一个是寻址方式不同,另外一个是IVT(Interrupt Vector Table).我们这篇 ...

  9. [HGE]-源码分析-11 sound

    音效部分. HGE的音效底层接口用的BASS库,做的事情就是把BASS库里的操作封装了一下. 这个文件里面函数挺多,外部的接口分为,Effect,music,Stream,Channel 先上图看看这 ...

最新文章

  1. linux文件夹加密访问,技术|Linux系统上用encfs创建和管理加密文件夹
  2. java velocity是什么意思,什么是Apache Velocity?
  3. javascript闭包产生的内存泄漏
  4. dvwa_xss_储存型
  5. Android分渠道打包(Python 3.4 实现)
  6. mysql多表查询方式_MySQL多表查询方式问题
  7. cut命令详解(转)
  8. 计算点在哪些四边形内
  9. springcloud服务网关-gateway
  10. s2sh框架搭建mysql_S2SH项目框架搭建(完全注解)
  11. 计算机专业师范类毕业论文,师范生毕业论文范文
  12. 如何提升APP日活(DAU)?
  13. 8、Android Studio 使用MNN进行Swin_Transformer分类识别
  14. 二、执行v8引擎示例代码
  15. python逢7跳过_07.报数游戏:7的倍数或含7的数跳过,趣说python循环里的break和continue...
  16. 【VMware环境下Linux磁盘空间(LVM)扩容方法】
  17. GitHub搭建的个人博客发表文章
  18. 老人与海好词100英文带翻译_老人与海英文读后感100字
  19. springboot设置拦截器的方法
  20. python匿名函数里用if_python匿名函数用法实例分析

热门文章

  1. 自动化测试,纸质图书 流程图,代码
  2. First name, Middle name, Last name
  3. 嵌入式系统下Microwindows的实现
  4. 使用乐鑫官方资源搭建基于Arduino的ESP32的开发环境
  5. css中background-size属性cover、contain、100%的含义案例详解
  6. html中一条单线这么设置,html单线表格制作方法
  7. 记一次聚拢Android线程实操
  8. python 依据某几列累加求和_如何用Python找出PSY超卖的股票?
  9. C语言基础——%X(十六进制)的几种不同输出格式
  10. 用python画简单花瓣_花瓣网花瓣爬虫