0

我正在编写这个引导加载程序,它只是在屏幕上打印出一些东西。这就是我迄今为止在组装中所拥有的:

    .globl _start

    .code16

_start:

    movw $0x0003, %ax
    int $0x10

    movb $0x0e, %ah
    movb $0x69, %al
    int $0x10

    movw $_header, %bx
    movb %bl, %al
    int $0x10

_header: .ascii "W\0"

    .org 0x1FE

    .byte 0x55
    .byte 0xAA

所以现在它打印 ASCII 69(“i”),但我希望它也打印.ascii声明。现在我只设置了它,"W"所以我可以很容易地找到它Objdump。我似乎无法访问该值(57)。我可以leal $_header, %edx等等,但是我似乎无法访问%edx.

我尝试使用lodsb,但我似乎无法弄清楚。我设置%di为 0x00,并设置%si为 with 的地址,_headerleal %si, _header随后我的lodsb后面int 0x10似乎没有打印任何内容。任何想法我都会很感激。

4

1 回答 1

1

这里:

movw $_header, %bx
movb %bl, %al

首先,movb %bl, %al不是从内存中读取一个字节到 中al,而是从 中读取一个字节bl。您想将其更改为:

movb (%bx), %al

要只取出一个字符,_header可以al直接从内存中加载该字符:

movb _header, %al

其次,也是最重要的,您似乎做了几个假设:

  1. 您的代码以cs=0x7c0, ip=0 开始运行。它可以是cs=0, ip=0x7c00 ,但是您的代码期望ip=0 (我从代码中推断出汇编程序开始使用隐式汇编它.org 0)。您应该使您的代码对第二个选项具有弹性。您可以使用跳转指令重新加载csip更合适的值,如下所示:jmp $0x7c0,$_next以及下一行的相应标签:_next:
  2. 您的代码以ds=0x7c0 开始运行。ds不保证设置为您可能想要或需要的任何值。你必须自己初始化它。

最后,最后一个之后会发生什么int $0x10

通过更正,您的代码应如下所示:

    .globl _start

    .code16

_start:
    /* .org 0 is implied here! But the code may start with ip != 0. */

    jmp $0x7c0,$_next
_next:
    /* We have just ensured that cs=0x7c0,ip=$_next */

    /* Let's now load data segment registers with proper values */
    movw %cs, %ax
    movw %ax, %ds
    movw %ax, %es

    movw $0x0003, %ax
    int $0x10

    movb $0x0e, %ah
    movb $0x69, %al
    int $0x10

    movw $_header, %bx
    movb (%bx), %al /* read into al a byte from memory at address from bx */
    int $0x10

    /* Halt execution, don't just execute whatever garbage is in memory */
    /*after the end of the code. */
_halt:
    hlt
    jmp _halt

_header: .ascii "W\0"

    .org 0x1FE

    .byte 0x55
    .byte 0xAA
于 2012-10-08T02:01:35.917 回答