技术标签: 源码阅读#bochs
现在我们来阅读邓志老师的《x86/x64体系探索及编程》,边阅读边将其代码放到bochs中运行,然后观察bochs的CPU是如何来模拟的。现在我们来详细分析ex3-2目录里面的内容。
自己在工作中经常看汇编代码,但是写汇编代码真的很少写过,我们现在一边分析着这段boot汇编代码一边回顾其如何编写。
; Int 19h 加载 sector 0 (MBR) 进入 BOOT_SEG 段, BOOT_SEG 定义为 0x7c00
org BOOT_SEG
start:
cli
; enable a20 line
FAST_A20_ENABLE
sti
; 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 $
The
bin
format provides an additional directive to the list given in chapter 7:ORG
. The function of theORG
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_SEG
start:
cli
# support.inc
BOOT_SEG equ 7c00h
我们使用前面配置好的IDA调试器来分析一下,果然其定位到7c00h处,我们继续往下分析。
clear_screen:
pusha
mov ax, 0x0600
xor cx, cx
xor bh, 0x0f ; white
mov dh, 24
mov dl, 79
int 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.
其实耐心分析一下,发现这些并不困难,之前每次看这些汇编代码都心气浮躁,看了一遍看似懂了,但转头让自己写,发现自己啥也写不出来。。。
mov si, hello
call print_message
print_message:
pusha
mov ah, 0x0e
xor bh, bh
do_print_message_loop:
lodsb
test al,al
jz do_print_message_done
int 0x10
jmp do_print_message_loop
do_print_message_done:
popa
ret
代码如下,我们现在有上面分析clear_screen函数的经历,再分析下面这个函数就轻松多了。
lodsb指令将si指针指向的数据加载来al寄存器中,然后指针自动加1.所以 lodsb之后,紧接着"test al,al“判断是否读到指针结尾,然后循环来进行处理。
因此,通过这个我们可以得知,其在汇编模式下没有一条指令可以让你全部输出内容,但是可以使用"lodsb+循环"的方式,连续调用int 0x10来连续输出字符串。
SETUP_SEG equ 8000h
mov si, 20 ; setup ģ���ڵ�20��������
mov di, SETUP_SEG - 2
call load_module ; ʹ�� load_module() ���������
load_module:
call read_sector ; read_sector(sector, buf)
test ax, ax
jnz do_load_module_done
mov cx, [di] ; ��ȡģ�� size
test cx, cx
setz al
jz do_load_module_done
add cx, 512 - 1
shr cx, 9 ; ���� block��sectors��
do_load_module_loop:
call dot
dec cx
jz do_load_module_done
inc si
add di, 0x200
call read_sector
test ax, ax
jz do_load_module_loop
do_load_module_done:
ret
代码如上,这个代码看了好久才理解。简单来说,我们在构造c.img时,使用的是LBA模式,但是当读取磁盘时,当不支持拓展读时,需要转而使用CHS模式。如果要使用 "int 0x13,ah = 0x2" 这种方式来读取磁盘,需要将LBA转换CHS,运算方法的解释网上有很多。
bochs的bios支持拓展读,可以使用"int 0x13,ah = 0x42",这样仅需要LBA而不需要CHS,下面是使用拓展读时寄存器的详细信息:
上面可以看到,源代码中注释存在一些问题,别在阅读时被误导了。
这段汇编中,有一个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=0
memory: guest=512, host=256
vgaromimage: file=D:/code/git_local_code/kkbochs-master/bochs-src/bios/VGABIOS-lgpl-latest
floppya: 1_44=/dev/fd0, status=inserted
ata0: 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=9
floppya: 1_44=demo.img, status=inserted
ata0-master: type=disk, path="c.img", mode=flat, cylinders=2, heads=16, spt=63
#boot: floppy
boot: disk
floppy_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.out
parport1: enabled=1, file="parport.out"
# keyboard_serial_delay: 250
# keyboard_paste_delay: 100000
mouse: enabled=0
private_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是如何实现它们的。
一、ArchUtilsjava运行环境的系统信息工具类getArch();// 获取电脑处理器体系结构 32 bit、64 bit、unknowngetType();// 返回处理器类型 x86、ia64、ppc、unknownis32Bit();// 检查处理器是否为32位is64Bit();// 检查处理器是否为64位isIA64();// 检查是否是英特尔安腾处理器类型i...
团队名称:梦飞翔团队简介:我们是由四个男生组成的团队,在开发的过程中,我们会团结合作,相互交流学习,让梦想飞翔。团队成员:王钢:逻辑思维好,精通算法,擅长java。博客地址:http://www.cnblogs.com/java-meng/孟祥通:善于学习,对细节精益求精,团队合作能力。博客地址:http://www.cnblogs.com/wanggang-java/...
umask 默认权限是 Linux 权限的一种,主要用于让 Linux 中的新建文件和目录拥有默认权限。Linux 是一个比较安全的操作系统,而安全的基础就是权限,所以,在 Linux 中所有的文件和目录都要有基本的权限,新建的文件和目录当然也要有默认的权限。在 Linux 中,通过 umask 默认权限来给所有新建立的文件和目录赋予初始权限,这一点和 Windows 不太一样,Windows 是...
在ORACLE数据库中,DBA_OBJECTS视图中OBJECT_TYPE为LOB的对象是什么东西呢?其实OBJECT_TYPE为LOB就是大对象(LOB),它指那些用来存储大量数据的数据库字段。下面演示一下: CREATE TABLE TEST( "ID" NUMBER, "NAME" NVARCHAR2(10), "TEST" CLOB) INSERT I...
linux 使用sendEmail 发送邮件失败, 检查日志的时候提示ERROR => ERROR => SMTP-AUTH: Authentication to smtp.126.com:25 failed.原因是sendEmail脚本的密码不是输入密码, 而是输入授权码!126邮箱要求授权码, 不是密码。#!/bin/bash/usr/local/bin/email/sendEmail -o tls=no -f 邮箱号@126.com -t qq邮箱号@qq.co...
一、第一步新建一个helloworld QT工程。二、使用qmake工具生成Makefile文件 在工程源码文件夹运行qmake “#/opt/qt-4.7.1/bin/qmake” ,生成Makefile文件,三、执行编译命令“#make”,如下图所示。四、生成了“helloworld”
前段时间,闲来无事,跟着朋友一起玩起打新股。现在疫情影响之下,股市波动还是很大的,特别美股出现了几次的熔断。港股需要开一个香港的银行账户,但现在又无法亲自过港,没法办理。后来朋友介绍了汇丰,说国内见证就可以开香港账户了。我就联系了,上星期下户了,过程还是比较简单的。我也就简单给大家分享一下吧主要考虑,不需要去亲自去香港,省去了签证或者港澳通行证的费用。因为是卓越理财的客户,所以在全球标识有银联...
阿里云ECS服务器配置LAMP时安装配置PHP扩展填坑(三)apache+mysql配置完成、问题解决后,接下来就是安装配置PHP了,按照阿里云官方lamp配置文档(https://help.aliyun.com/document_detail/50774.html)正常安装一般是没有问题的(建议安装配置编译PHP的时候加上--with-gd \),但是,无论进行什么操作都会有warnni
List<YourEntity> resultList = newArrayList<>();model.addAttribute("resultList", JSON.toJSONString(resultList));var result = '${resultList}';var resultList = JSON.parse(result);
通常文本编辑器都提供了一些和编辑相关的快捷键,在Eclipse中也可以通过这些快捷键进行文本编辑。1. 【Ctrl+C】:复制。2. 【Ctrl+X】:剪切。3. 【Ctrl+V】:粘贴。4. 【Ctrl+S】:保存文件。5. 【Ctrl+Z】:撤销。6. 【Ctrl+Y】:重复。7. 【Ctrl+F】:查找。eclipse 常用快捷键1. 【ALT+/】
CALayer标签(空格分隔): ios进阶CALayerCALayer的基本介绍在iOS中,你能看得见摸得着的东西基本上都是UIView,其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层,在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层 @property(nonatomic,readonly,