Assembly 汇编(x86):<;标签>;db';字符串';,除非存在';这是跳转指令

Assembly 汇编(x86):<;标签>;db';字符串';,除非存在';这是跳转指令,assembly,x86,bootloader,16-bit,Assembly,X86,Bootloader,16 Bit,我一直把头撞在墙上,试图理解为什么下面的程序集没有正确地转储“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”的内容

; 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_开机输出

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
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

执行从顶部开始。如果省略
jmp start
,那么字符h将被CPU解释为一条指令。你肯定知道这是不正确的吗

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


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

由于您正在创建引导扇区,执行从生成文件的第一个字节开始。它不会从开始标签或其他任何地方开始。由于字符串“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]
...

非常感谢用户3144770。出于好奇,有什么原因我不能把HELLO_WORLD的地址(因为它是一个标签)放在一个寄存器中,然后进行迭代?(我在想字节流)
mov-si,HELLO\u-WORLD
已经按照你的要求做了。(NASM语法)问题是,如果我尝试使用:mov al,[SI]它终止于cmp al,0,我看不出有什么问题。这正是您在向我们展示的引导加载程序中所需要的。文本“hello world”必须在某个时候结束,在这里添加一个零字节并检查它。谢谢-绝对有意义。也问了下面的问题:出于好奇,有什么原因我不能把HELLO_WORLD的地址(因为它是一个标签)放在一个寄存器中,稍后再进行迭代?(我在想字节流)
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]
...