gpt4 book ai didi

assembly - 当第二阶段引导加载程序的一部分时,INT 10h/ah=13h 不打印字符串

转载 作者:行者123 更新时间:2023-12-02 14:42:25 31 4
gpt4 key购买 nike

我使用了第一个扇区中的所有内存,现在我想在第二个扇区(第二阶段)中存储一个新的变量字符串并打印它。例如:

hello db 'Hello World'

新字符串应该位于另一个扇区中(因为第一个扇区中没有更多内存)。我用 INT 13h,ah=2 做到了这一点读取第二个磁盘扇区到地址 900h:0000。我将变量 hello 以及要打印的代码存储在该扇区中。当我使用 INT 10h/ah=13h 时,它无法打印我的字符串在这样的代码中:

mov ax, 7c0h
mov es, ax

mov bp, hello
mov ah,13h ; function 13 - write string
mov al,01h ; attrib in bl, move cursor
mov bl,0bh ; attribute - magenta
mov cx,30 ; length of string
mov dh,1 ; row to put string
mov dl,4 ; column to put string
int 10h ; call BIOS service

当变量位于第一个扇区时,它打印得很好,但是当我将它存储在第二个扇区时,它不会打印,即使我这样做了:

mov ax, 900h
mov es, ax

示例代码:

xchg bx, bx
mov ax, 7c0h
mov ds, ax

sector_2:
mov bx, 900h
mov es, bx
mov bx, 0
mov ah, 2
mov al, 1
mov ch, 0
mov cl, 2
mov dh, 0
mov dl, 80h
int 13h
call 900h:0000

jmp $

times 510 - ($-$$) db 0 ; Fill empty bytes to binary file
dw 0aa55h ; Define MAGIC number at byte 512
;;;;;;;;;;;;;;;;;;;;;;;;

sector_2:
mov ax, 900h
mov es, ax
mov bp, hello
mov ah,13h ; function 13 - write string
mov al,01h ; attrib in bl, move cursor
mov bl,0bh ; attribute - magenta
mov cx,5 ; length of string
mov dh,1 ; row to put string
mov dl,4 ; column to put string
int 10h ; call BIOS service

retf
jmp $

hello db 'Hello'
times 1024 - ($-$$) db 0
times 2*8*63*512 - ($-$$) db 0

最佳答案

我认为您的示例代码中存在一些复制和粘贴错误。您写道:

xchg bx, bx
mov ax, 7c0h
mov ds, ax

但我认为你的意思是:

xchg bx, bx
mov ax, 7c0h
mov es, ax ; Int 10h/ah=13h takes string address in ES:BP

您的代码在第一个片段中是正确的。您的示例有两个 sector_2 标签,因此可能会导致 NASM 一些悲伤。我相信您应该删除代码中第一次出现的标签。

我假设您正在使用以下内容组装代码:

nasm -f bin boot.asm -o boot.img

文件名会有所不同,您可以省略-f bin,因为它是默认的。

<小时/>

由于您的代码中没有显式的 ORG 指令,NASM 默认情况下假定为 org 0h。所有绝对内存引用都是相对于偏移量 0 的。在您的情况下,这就是您想要的汇编程序文件的第一个扇区(512 字节)。您已将引导加载程序编码为使用 0x7c0 段,您选择的段和原点 0 应指向物理地址 7c00h。在 segment:offset寻址你会有 (7c0h<<4)+0 (其中 0 是起源/组织),这会产生 7c00h 的正确结果。

所以一切都很好,您可以在 900h:0h 正确地将扇区读入内存。然后,您可以通过 call 900h:0000 从引导加载程序的第一阶段对其进行FAR CALL。这也是正确的。

如果这一切都是正确的,问题出在哪里?问题是 NASM 不知道您将前 512 字节之后的代码加载到内存中的另一个位置,并且使用的段:偏移量将再次相对于 0 (900h:0000h)。它将继续生成相对于引导加载程序开头的绝对地址。

如果您使用 NDISASM 显示从磁盘镜像的字节 512 开始生成的代码,您会发现问题:

00000000  B80009            mov ax,0x900
00000003 8EC0 mov es,ax
00000005 BD1A02 mov bp,0x21a
00000008 B413 mov ah,0x13

这是使用以下命令生成的:

ndisasm -e 512 -b16 boot.img

boot.img 是您生成的镜像文件的名称。 -e 512 表示跳过反汇编文件的前 512 个字节。我只对输出的前几行感兴趣,特别是:

mov bp,0x21a

0x21ahello的偏移量。但请注意,0x21a 是十进制 538,这将是相对于整个引导加载程序开头的偏移量,而不是相对于 0 (900h:0000h) 的偏移量。要解决此问题,您需要指示NASM第二阶段(第二扇区)生成的代码需要相对于原点 0,而不是相对于引导加载程序的开头。通过将第二阶段(第二个扇区)放置在原点 (vstart) 重置为 0 的新部分中,可以轻松完成此操作。这可以通过在第二阶段的开头放置这样的部分指令来完成:

section stage2, vstart=0h

所以在你的代码中它看起来像:

dw 0aa55h                          ; Define MAGIC number at byte 512
;;;;;;;;;;;;;;;;;;;;;;;;

section stage2, vstart=0h ; Section name can be anything of your choosing
sector_2:
mov ax, 900h
mov es, ax
mov bp, hello

现在,如果您查看 NDISASM 输出,它将如下所示:

00000000  B80009            mov ax,0x900
00000003 8EC0 mov es,ax
00000005 BD1A00 mov bp,0x1a ; Notice hello offset is 0x1a not 0x21a
<小时/>

@Jester 的做法是正确的,将 org 0h 放置在第二阶段代码(第二个扇区)之前,但每个程序集中只能有一个 ORG 指令文件。无论您将其放置在文件中的哪个位置,NASM 都会表现得好像它确实在文件顶部找到了它一样。这种行为没有很好的记录!杰斯特的解决方案不会改变任何事情。 NASM 的“SECTION 指令可以在汇编文件中的任何位置使用来重置原点(在本例中为 0)。

有关 ORGSECTION 指令的更多信息可以在 NASM documentation 中找到。 。 SECTION 指令和 VSTART 参数记录在第 7.1.3 节 bin 格式的多节支持

关于assembly - 当第二阶段引导加载程序的一部分时,INT 10h/ah=13h 不打印字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38072520/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com