- 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/
我尝试在安装了多类型 MFC 库的 visual studio 2015 MFC 上运行以前编写的 MFC c++ 代码。 但是,我这里仍然有 12 个关于缺少函数的错误: IntelliSense:
我正在学习 OOP 并且有疑问。假设我有一个包含 ClassB.h 的文件 ClassA.h,并且在某些时候我的 ClassB.h 需要包含 ClassA .h。 这会产生一个错误,我想我明白为什么会
我开始使用 CUDA 进行编程,在一些示例中我找到了包含文件 cuda.h、cuda_runtime.h 和 cuda_runtime_api.h 包含在代码中。有人可以向我解释一下这些文件之间的区别
我有一些生成正则表达式的代码。那么下面的表达式实际上是: ^(?:\s*((exclude|include|hide|show|protect|risk|dir-merge|merge)),\s*((
我一直在查看一些源代码,以更好地了解我们使用的这款游戏的核心,并编写更可靠、更快速的插件。然后我发现了这段奇怪的代码...... public void setMaxH(double amount)
通常我们会使用标准类型作为 std::unordered_map 的键和值.但现在我需要自定义我自己的键和值类。 键类在block_cache_key.h 中定义如下: #ifndef BLOCK_C
例如,我想要两个头文件,它们可以依赖于另一个头文件中的函数。 //Header1.h file #include Header2.h void h1(){ //... func1(); } v
我正在研究来自 Sedgewick 的 Shell 排序 Algorithms in C part 1-4在第 172 页。 我使用 size (数组的长度),而不是 l和 r (开始和结束);所以我
我在 macOS BigSur 上通过 VMWare 使用 Ubuntu 20.04.2 LTS。我安装了最新版本的 tcl、tcl-dev、tk 和 tk-dev - 版本 8.6。我想编译 Arc
我用我的 glu 和 gl 头文件构建了一个 OpenGL 程序,默认包含在 windows 7 专业版中。现在,我买了一本描述 OpenGL 游戏开发的书。这本书的作者说,我必须在我的项目中包含 g
我想在 token 中保留特殊字符,同时仍对特殊字符进行 token 化。说我有话 "H&R Blocks" 我想将其标记为 "H", "R", "H&R", "Blocks" 我读了http://w
关于 hash 作为 trans 参数的另一个问题。在下面的代码中,简单地使用 hash 会给出不正确的结果,但是将其替换为 keys 和 values 会使其正确。怎么了? my @alph1 =
我已经编写了一个 C 程序,它获取屏幕像素的 RGB 值 (0-255),并知道其位置 (x,y)。它可以在 Linux 中运行,但是当我尝试在 Visual Studio (Windows) 中编译
我已经使用 Windows 7 专业版中默认包含的 glu 和 gl 头文件构建了一个 OpenGL 程序。现在,我买了一本描述 OpenGL 游戏开发的书。这本书的作者说,我必须将glew head
#include using namespace std; #include //#include int main() { initscr();
h:messages h:form 内的组件还显示与外部组件相关的消息。 如何限制它只显示与包含 h:form 内的组件相关的消息? 我不喜欢用单独的h:message来使我的代码膨胀。每个输入组件的
我下载了示例代码和 cpp 文件,其中包含 list.h、queue.h 和 vector.h 等头文件,如果我尝试构建,我会收到“ fatal error :没有这样的文件或目录编译终止”我想我应该
我有一个编译成功的桌面项目,但是在我向项目添加新配置以支持 Windows Mobile 平台后,我收到以下错误: error C2146: syntax error : missing ';' be
有很多关于这个错误的帖子,但我无法解决它,我希望你能拿出解决方案。我在 Ubuntu 机器上。 ~/graphmap2$ 在这个文件夹中,我下载了 zlib。可以看图 经过一番谷歌搜索后,我还注意到没
是否可以在 Visual C++ 中使用以下 header : 图.h dos.h bios.h 最佳答案 据我所知,无法在 Visual C++ 中使用它, 与此同时,我希望您关注 Open Wat
我是一名优秀的程序员,十分优秀!