- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在编写一个在 QEMU 中作为引导加载程序运行的 x86 实模式汇编程序时遇到问题。我正在尝试通过 BIOS 中断 0x10 打印文本。我的代码是:
print:
pusha
.loop:
mov AL, [SI]
cmp AL, 0
je .end
call printChar
inc SI
jmp .loop
.end:
popa
ret
printChar:
pusha
mov AH, 0x0E
mov BH, 0
mov BL, 0x0F
int 0x10
popa
ret
我使用 [ORG 0x7c00]
作为原点。我测试了 printChar 标签并用 AL 中的一些字母调用它,它工作正常。当我尝试将内存地址加载到这样的消息时:
loadMsg db "Loading",0
mov SI, loadMessage
call print
我在 QEMU 模拟器上得到像“U”这样的垃圾输出。昨天,我写了一段和这个非常相似的代码,一点问题都没有。是什么导致了我的问题,如何解决?
最佳答案
我最近写了一些General Bootloader Tips在可能对您有用的 Stackoverflow 答案中。可能提示 #1 适用于您的问题:
When the BIOS jumps to your code you can't rely on CS,DS,ES,SS,SP registers having valid or expected values. They should be set up appropriately when your bootloader starts. You can only be guaranteed that your bootloader will be loaded and run from physical address 0x00007c00 and that the boot drive number is loaded into the DL register.
基于 printChar 有效的事实,并且写出整个字符串并不意味着 DS:SI 没有指向内存中的正确位置你的字符串驻留。这通常是因为当 BIOS 跳转到引导加载程序时,开发人员错误地假设 CS 和/或 DS 寄存器已正确设置。它必须手动设置。在原点为 0x7c00 的情况下,DS 需要设置为 0。在 16 位实模式中,物理内存地址是从 segment:offset pairs 计算得出的。使用公式 (segment<<4)+offset
.在您的情况下,您使用的是偏移量 0x7C00。 DS 中的值为 0 将产生 (0<<4)+0x7c00 = 0x07c00 的正确物理地址。
您可以在程序开始时将 DS 设置为 0,方法如下:
xor ax, ax ; set AX to zero
mov ds, ax ; DS = 0
对于 QEMU,BIOS 跳转到 0x07c0:0x0000。这也代表相同的物理内存位置 (0x07c0<<4)+0 = 0x07c00 。这样的跳转将设置 CS=0x07c0(不是 CS=0)。由于有许多段:偏移量对映射到相同的物理内存位置,因此您需要适本地设置 DS。您不能指望 CS 是您期望的值。所以在 QEMU 中,这样的代码甚至不会正确设置 DS(使用 ORG 0x7c00
时):
mov ax, cs
mov ds, ax ; Make DS=CS
这可能适用于一些模拟器,如 DOSBOX 和一些物理硬件,但不是全部。这段代码可以工作的环境是当 BIOS 跳转到 0x0000:0x7c00 时。在那种情况下,CS 在到达您的引导加载程序代码时将为零,并且将 CS 复制到 DS 会起作用。不要假设 CS 在所有环境中都为零是我的要点。始终将段寄存器设置为您明确想要的内容。
应该工作的代码示例是:
BITS 16
ORG 0x7c00
GLOBAL main
main:
xor ax, ax ; AX = 0
mov ds, ax ; DS = 0
mov bx, 0x7c00
cli ; Turn off interrupts for SS:SP update
; to avoid a problem with buggy 8088 CPUs
mov ss, ax ; SS = 0x0000
mov sp, bx ; SP = 0x7c00
; We'll set the stack starting just below
; where the bootloader is at 0x0:0x7c00. The
; stack can be placed anywhere in usable and
; unused RAM.
sti ; Turn interrupts back on
mov SI, loadMsg
call print
cli
.endloop:
hlt
jmp .endloop ; When finished effectively put our bootloader
; in endless cycle
print:
pusha
.loop:
mov AL, [SI] ; No segment on [SI] means implicit DS:[SI]
cmp AL, 0
je .end
call printChar
inc SI
jmp .loop
.end:
popa
ret
printChar:
pusha
mov AH, 0x0E
mov BH, 0
mov BL, 0x0F
int 0x10
popa
ret
; Place the Data after our code
loadMsg db "Loading",0
times 510 - ($ - $$) db 0 ; padding with 0 at the end
dw 0xAA55 ; PC boot signature
关于assembly - BIOS int 10h 在 QEMU 上打印垃圾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33974115/
我是 C 新手,还没有真正掌握 C 何时决定释放对象以及何时决定保留对象。 heap_t 是指向结构堆的指针。 heap_t create_heap(){ heap_t h_t = (heap
我有一个问题,我不知道如何解决。问题是: char * ary = new Char[]; ifstream fle; fle.open(1.txt, ios_base::binary); fle.s
假设我在 C# 中有字符串:“我看不到你……” 我想删除(替换为空等)这些“’”符号。 我该怎么做? 最佳答案 那个“垃圾”看起来很像有人将 UTF-8 数据解释为 ISO 8859-1 或 Wi
我无法在解析方法中更改蜘蛛设置。但这绝对是一种方式。 例如: class SomeSpider(BaseSpider): name = 'mySpider' allowed_domains
在开始之前,我们先回顾一下堆是个什么玩意,大家可能都知道,我们每天创建的Java对象几乎都存放在堆上面,所以说堆是一个巨大的对象池一点都不过分,在这个对象池里面管理者数据巨大的对象实例。 在对
我想知道为什么 printf() 在提供数组且没有格式化选项时成功打印字符数组,但在使用整数数组时编译器会抛出警告并打印垃圾值。 这是我的代码: #include int main() { c
我正在研究 Scrapy 库并尝试制作一个小爬虫。 这是爬虫的规则: rules = ( Rule(LinkExtractor(restrict_xpaths='//div[@class="w
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Printing a string to a temporary stream object in C++
这个问题在这里已经有了答案: Are WebGL objects garbage collected? (2 个答案) 关闭 3 年前。 在 WebGL 中,纹理的创建和销毁使用: WebGLTex
我继承了以下代码: (为保护无辜者更改了一些名称。) package foo.bar.baz; import javax.swing.JPanel; //Main panel in the GUI c
如果我没记错的话,在某些情况下,Java 中的 lambda 会生成为匿名类实例。例如,在这段代码中,lambda 需要从外部捕获一个变量: final int local = 123456; lis
我正在阅读托管代码中的内存泄漏,想知道是否可以在 C# 不安全代码中创建它? unsafe { while(true) new int; } 我不确定如果它作为不安全代码运行,是否会被 GC
假设我有以下用 HTML 编写的网页(仅正文部分): ... function fn() { // do stu
我想知道是否有简单的命令可以删除在 latex 编译过程中生成的所有不必要的文件,例如.aux、.log 等 最好将它链接到常规的 Latex 构建命令,这样在我点击“编译”后,垃圾文件就会被删除。
Java 在 Java7 中引入了带有字符串的 switch case。我想知道使用这样的开关盒是否会产生垃圾。 例如在我的程序中, String s = getString(); switch(s)
Cevelop将 char junk 作为“未初始化的变量”对象。在这种情况下,解决问题的正确方法是什么? friend std::ostream& operator>(std::istream&
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and t
我正在编写一个发送和接收纯文本的小型 boost asio tcp 服务器和客户端。通信或多或少是请求响应。在测试期间,我想我只是向服务器发送垃圾数据,向它发送 100.000 个请求。 客户端发
我正在使用 SAX 来读取/解析 XML 文档,并且它工作正常,除了这个特定的站点,在该站点中 eclipse 告诉我“文档元素之后的垃圾”并且我没有返回任何数据 http://www.zachblu
这是我的 Scrapy 爬虫代码。我正在尝试从网站中提取元数据值。没有元数据在一个页面上出现多次。 class MySpider(BaseSpider): name = "courses"
我是一名优秀的程序员,十分优秀!