组件 (x86):<标签>db 'string',0 不会被执行,除非有跳转指令

发布于 2025-01-11 22:59:42 字数 2445 浏览 1 评论 0原文

我一直在用头撞墙,试图理解为什么下面的程序集没有正确转储“HELLO_WORLD”的内容。

; Explicitly set 16-bit
[ BITS 16 ]
[ ORG 0x7C00 ]

; Create label for hello world string terminated by null.
HELLO_WORLD db 'hello world', 0

start:
    ; Move address of HELLO_WORLD into si
    mov SI, HELLO_WORLD
    call print_string

    ; Continue until the end of time
    jmp $

print_string:
    loop:
        ; Retrieve value stored in address at si
        mov al, [SI]
        mov ah, 0x0E
        cmp al, 0
        ; Finish execution after hitting null terminator
        je  return
        INT 0x10
        ; Increment contents of si (address)
        inc SI
        jmp loop

    return:
        ret

; boot loader length *must* be 512 bytes.
times 510-($-$$) db 0
dw 0xAA55

最后,我发现如果我们不执行(使其不编码)标签,那么它就能正确运行。

jmp start
HELLO_WORLD db 'hello world',0    

我发现最令人困惑的部分是,查看十六进制转储,HELLO_WORLD 仍然在二进制文件中(在开始时 - 并且其类型似乎没有区别)。

cat nojmp_boot.out

00000000  68 65 6c 6c 6f 20 77 6f  72 6c 64 00 be 00 7c e8  |hello world...|.|
00000010  02 00 eb fe 8a 04 b4 0e  3c 00 74 05 cd 10 46 eb  |........<.t...F.|
00000020  f3 c3 eb e8 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200

cat jmpboot.out

00000000  eb 22 68 65 6c 6c 6f 20  77 6f 72 6c 64 00 be 02  |."hello world...|
00000010  7c e8 02 00 eb fe 8a 04  b4 0e 3c 00 74 05 cd 10  ||.........<.t...|
00000020  46 eb f3 c3 eb e8 00 00  00 00 00 00 00 00 00 00  |F...............|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200

检查前两个字节,我们可以看到“e8 22”是到地址 22 的短跳转(http://net.cs.uni-bonn.de/fileadmin/user_upload/plohmann/x86_opcode_struct_and_instruction_overview.pdf)。

我的问题是:

为什么我们不能将“HELLO_WORLD”作为程序执行的一部分,就我而言,代码和数据之间没有区别?

我使用以下内容进行编译:

nasm -f bin -o boot.bin boot.asm && if [ $(stat -c "%s" boot.bin) -ne 512 ]; then x; fi && qemu-system-x86_64 boot.bin

I've been banging my head against the wall in an attempt to understand why the following assembly is not correctly dumping the contents of 'HELLO_WORLD'.

; Explicitly set 16-bit
[ BITS 16 ]
[ ORG 0x7C00 ]

; Create label for hello world string terminated by null.
HELLO_WORLD db 'hello world', 0

start:
    ; Move address of HELLO_WORLD into si
    mov SI, HELLO_WORLD
    call print_string

    ; Continue until the end of time
    jmp $

print_string:
    loop:
        ; Retrieve value stored in address at si
        mov al, [SI]
        mov ah, 0x0E
        cmp al, 0
        ; Finish execution after hitting null terminator
        je  return
        INT 0x10
        ; Increment contents of si (address)
        inc SI
        jmp loop

    return:
        ret

; boot loader length *must* be 512 bytes.
times 510-($-$) db 0
dw 0xAA55

In the end, I discovered that if we do not execute (make it not code) the label, then it functions correctly.

jmp start
HELLO_WORLD db 'hello world',0    

The part I find the most confusing, looking at the hex dump, HELLO_WORLD is still in the binary (at the beginning - and there appears to be no distinction of its type).

cat nojmp_boot.out

00000000  68 65 6c 6c 6f 20 77 6f  72 6c 64 00 be 00 7c e8  |hello world...|.|
00000010  02 00 eb fe 8a 04 b4 0e  3c 00 74 05 cd 10 46 eb  |........<.t...F.|
00000020  f3 c3 eb e8 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200

cat jmpboot.out

00000000  eb 22 68 65 6c 6c 6f 20  77 6f 72 6c 64 00 be 02  |."hello world...|
00000010  7c e8 02 00 eb fe 8a 04  b4 0e 3c 00 74 05 cd 10  ||.........<.t...|
00000020  46 eb f3 c3 eb e8 00 00  00 00 00 00 00 00 00 00  |F...............|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200

Inspecting the first two bytes, we can see 'e8 22' is a shortjump to address 22 (http://net.cs.uni-bonn.de/fileadmin/user_upload/plohmann/x86_opcode_structure_and_instruction_overview.pdf).

My question is:

Why can we not have 'HELLO_WORLD' as a part of the execution of the program, as far I was concerned, there was no distinction between code and data?

I'm using the following for compilation:

nasm -f bin -o boot.bin boot.asm && if [ $(stat -c "%s" boot.bin) -ne 512 ]; then x; fi && qemu-system-x86_64 boot.bin

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

彻夜缠绵 2025-01-18 22:59:42

执行从顶部开始。如果省略jmp start,那么字符h将被CPU解释为一条指令。你一定明白这样的说法是不正确的吧?

就我而言,代码和数据之间没有区别?

当我们考虑代码和数据在二进制文件中的位置时,代码和数据之间没有区别。但代码和数据仍然是两个完全不同的项目。代码是唯一可以由 CPU执行的代码。

Execution starts at the top. If you omit the jmp start then the character h will get interpreted by the CPU as if it were an instruction. Surely you see that such can not be correct?

as far I was concerned, there was no distinction between code and data?

There's no distinction between code and data when we consider their placement in the binary. But code and data still remain 2 completly different items. Code being the only one that can get executed by the CPU.

混吃等死 2025-01-18 22:59:42

由于您正在创建引导扇区,因此执行从生成文件的第一个字节开始。它不会从开始标签或其他任何地方开始。由于字符串“hello world”位于文件的开头,这些字节是首先执行的。这些字节被 CPU 解释为指令,而不是字符,并且它们按照解码后的任何指令执行。

以下是执行的指令:

7c00:   68 65 6c                push   0x6c65
7c03:   6c                      ins    BYTE PTR es:[di],dx
7c04:   6f                      outs   dx,WORD PTR ds:[si]
7c05:   20 77 6f                and    BYTE PTR [bx+0x6f],dh
7c08:   72 6c                   jb     0x7c76
7c0a:   64 00 be 00 7c          add    BYTE PTR fs:[bp+0x7c00],bh
7c0f:   e8 02 00                call   0x7c14
7c12:   eb fe                   jmp    0x7c12
7c14:   8a 04                   mov    al,BYTE PTR [si]
...

Since you're creating a boot sector the execution begins at the first byte of the generated file. It won't begin at the start label or anywhere else. Since the string "hello world" is at the start of the file these bytes are what get executed first. These bytes are interpreted by the CPU as instructions, not characters, and they get executed as whatever instructions they get decoded as.

Here are the instructions that get executed:

7c00:   68 65 6c                push   0x6c65
7c03:   6c                      ins    BYTE PTR es:[di],dx
7c04:   6f                      outs   dx,WORD PTR ds:[si]
7c05:   20 77 6f                and    BYTE PTR [bx+0x6f],dh
7c08:   72 6c                   jb     0x7c76
7c0a:   64 00 be 00 7c          add    BYTE PTR fs:[bp+0x7c00],bh
7c0f:   e8 02 00                call   0x7c14
7c12:   eb fe                   jmp    0x7c12
7c14:   8a 04                   mov    al,BYTE PTR [si]
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文