我正在使用 NASM 来汇编我的汇编代码。我组装的代码如下所示:
[BITS 32]
[ORG 0]
jmp 07c0h:start
testvar db 0, 0, 0, 0, 0, 0, 4, 8, 15, 16, 23, 42
start:
mov byte [testvar], 47
hang:
jmp hang
times 510-($-$$) db 0
dw 0AA55h
我对另一段代码遇到了问题,我注意到我无法修改内存,所以我编写了这段代码来测试是否确实如此。是的!我将汇编的机器代码复制到软盘的第一个扇区,程序运行(我使用 MS VirtualPC)。我检查了分配给 Virtual PC 的 RAM 内存并搜索了数字 4 8 15 16 23 42,这样我就可以找到二进制代码被复制的位置。数据的第一个字节未被触及。为什么会这样呢?
I am using NASM to assemble my assembler code. The code I assembled looks like this:
[BITS 32]
[ORG 0]
jmp 07c0h:start
testvar db 0, 0, 0, 0, 0, 0, 4, 8, 15, 16, 23, 42
start:
mov byte [testvar], 47
hang:
jmp hang
times 510-($-$) db 0
dw 0AA55h
I had problems with another piece of code, I noticed that I couldn't modify memory, so I wrote this piece of code to test if that was actually the case. It was! I copied the assembled machine code to the first sector of a floppy, the program ran (I used MS VirtualPC). I checked RAM memory assigned to Virtual PC and searched for numbers 4 8 15 16 23 42, so that I could find where the binary code was copied. The first byte of the data was not touched. Why is it so?
发布评论
评论(4)
简单的答案是,相同的代码汇编为 32 位与汇编为 16 位是不同的。引导扇区代码(以及所有加载的代码)在 16 位实模式下运行,直到 CPU 模式切换。
令人高兴的答案是列表显示了差异。
与 32 位相同的代码
作为 16 位运行时的等效代码
The simple answer is that the same code assembled as 32 bit is different than that assembled as 16 bit. Boot sector code (and all loaded code) is run in 16 bit real mode until the CPU mode is switched.
The happy answer is a listing shows the difference.
The same code as 32 bit
The equivalent code when run as 16 bit
在源文件中设置“BITS 32”只会影响汇编器吐出的操作码。
要执行 32 位代码,您需要将处理器模式更改为 32 位保护模式。通常,当稍微超出您的第一个玩具引导扇区时,您将分多个步骤进行内核加载。首先是 16 位引导扇区,其大小有限制。这会加载一个 16 位引导加载程序,进而可以设置保护模式。一些设计将这个 16 位部分保持最小,并进一步使用 32 位引导加载程序来加载内核,其他设计直接从 16 位引导加载程序加载内核。
我建议你看看 http://wiki.osdev.org/Main_Page , http://www.asmcommunity.net/ 和 http://board.flatassembler.net/ :)
Setting "BITS 32" in your source file only affects the opcodes the assembler spits out.
To execute 32bit code, you'll need to change the processor mode to, surprise surprise, 32bit protected mode. Typically, when moving a bit beyond your very first toy bootsector, you'll do your kernel loading in multiple steps. First, the 16bit bootsector, with all it's size constraints. This loads a 16bit bootloader, which in turn can set up protected mode. Some designs keep this 16bit part minimal and further uses a 32bit bootloader for loading the kernel, other designs load the kernel directly from the 16bit bootloader.
I suggest you take a look at http://wiki.osdev.org/Main_Page , http://www.asmcommunity.net/ and http://board.flatassembler.net/ :)
除了
bits 32
对于引导加载程序代码来说是错误的之外,还有一个问题是您没有将ds
设置为任何内容,因此它将保留 ROM-BIOS 最后放入其中的任何内容。您希望使用mov ax, 7C0h
\mov ds, ax
来修复该问题(当使用org 0
时)。An issue other than
bits 32
being wrong for boot loader code is that you do not setds
to anything, so it will retain whatever the ROM-BIOS put into it last. You wantmov ax, 7C0h
\mov ds, ax
to fix that (when usingorg 0
).我的理解是PC兼容机都以16位模式启动(出于兼容性原因)。
因此,在我看来,您需要从 [BITS 16] 开始,即使第一条指令是跳转到 32 位模式并且紧随其后的是 [BITS 32]。
请参阅NASM:混合 16 位和 32 位代码。
我对软盘启动过程有点模糊。
您确定代码位于实际执行的位置吗?
是否可以单步执行该代码?
My understanding is that PC compatible machines all start in 16 bit mode (for compatibility reasons).
So it seems to me that you need to begin with [BITS 16], even if the first instruction is a jump to to 32 bit mode and is immediately followed by [BITS 32].
See NASM: Mixing 16 and 32 Bit Code.
I'm a little fuzzy on the floppy boot process.
Are you sure the code is located where it will actually be executed?
Is it possible to single-step through that code?