x86 程序集:了解数据库语法
x86 assembly: Understanding db syntax
我刚刚开始学习 x86 汇编,方法是阅读我找到的一本在线书籍:http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf
当我阅读这本书并按照示例进行操作时,我 运行 遇到了一个我无法解决的问题,由于我自己对汇编的无知运行,或者可能是编程一般的。我试图在我的引导扇区程序中构建一些代码,这些代码可以打印以 null 结尾的字符串,但该程序只打印第一个字符。
这是我尝试的一些示例代码 运行:
[org 0x7c00]
mov bx, Hello
mov ah, 0x0e
Keep_Printing:
mov al, [bx]
cmp al, 0
je Finished_Printing
int 0x10
add bx, 0x0008
jmp Keep_Printing
Finished_Printing:
cli
hlt
Hello:
db "Hello", 0
times 510-($-$$) db 0
dw 0xAA55
我在想会发生什么情况是 bx 将包含 Hello 的前两个字母的内存地址,但我不确定当我尝试将那个 16 位寄存器的内容移动到8位的人。当我 运行 它时,它只打印 'H' 所以我猜前 8 位进入 al,其余的被忽略?
在那之后,我希望程序在遍历字符串时不断检查 al 是否为 0,如果不是 0 则打印到屏幕上。我不确定如何迭代通过汇编中的一个字符一个字符的字符串,但我认为既然我有 Hello 的起始地址,我可以继续向 bx 中的内存地址添加 8 位。根据 'H' 之后我在内存中输入的内容,打印的内容会发生变化,但我不确定为什么它不是字符串的其余部分。
我确定我在各个层面上都误解了各种事情,但希望这里有人可以帮助澄清。谢谢!
内存地址在bytes
,而不是bits
,所以你需要添加1个字节,而不是8位。如您所见,将 8 添加到 BX
将寻址 H
上方的内存 8 bytes
,这将是一个 0
字节(因为您指定 times 510-($-$$) db 0
(现在,用 0
字节填充字节 510。
解决方案:将 1
添加到 BX,而不是 8
(使用 INC BX
可能会更好 - 更快更短)。
btw: mov al,[bx]
意思是'将 BX 指向的 BYTE(即寄存器 BX 中包含的地址)移动到 AL`
db
表示 define BYTE
,而不是 bit
正如用户@Magoo 所说,db
表示 'define byte' 因此要遍历字符串,您需要将指针递增 1 而不是 8。
切勿使用BX作为通过BIOS电传功能输出的文本地址。 BH应该是显示页面参数!!!
在您的代码中它 有效 因为文本 "Hello" 在内存中足够低以至于 BH=0。但这是巧合。
[org 0x7c00]
mov si, Hello
mov ah, 0x0e
Keep_Printing:
mov al, [si]
cmp al, 0
je Finished_Printing
int 0x10
add si, 1
jmp Keep_Printing
Finished_Printing:
cli
hlt
Hello:
db "Hello", 0
times 510-($-$$) db 0
dw 0xAA55
我刚刚开始学习 x86 汇编,方法是阅读我找到的一本在线书籍:http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf
当我阅读这本书并按照示例进行操作时,我 运行 遇到了一个我无法解决的问题,由于我自己对汇编的无知运行,或者可能是编程一般的。我试图在我的引导扇区程序中构建一些代码,这些代码可以打印以 null 结尾的字符串,但该程序只打印第一个字符。
这是我尝试的一些示例代码 运行:
[org 0x7c00]
mov bx, Hello
mov ah, 0x0e
Keep_Printing:
mov al, [bx]
cmp al, 0
je Finished_Printing
int 0x10
add bx, 0x0008
jmp Keep_Printing
Finished_Printing:
cli
hlt
Hello:
db "Hello", 0
times 510-($-$$) db 0
dw 0xAA55
我在想会发生什么情况是 bx 将包含 Hello 的前两个字母的内存地址,但我不确定当我尝试将那个 16 位寄存器的内容移动到8位的人。当我 运行 它时,它只打印 'H' 所以我猜前 8 位进入 al,其余的被忽略?
在那之后,我希望程序在遍历字符串时不断检查 al 是否为 0,如果不是 0 则打印到屏幕上。我不确定如何迭代通过汇编中的一个字符一个字符的字符串,但我认为既然我有 Hello 的起始地址,我可以继续向 bx 中的内存地址添加 8 位。根据 'H' 之后我在内存中输入的内容,打印的内容会发生变化,但我不确定为什么它不是字符串的其余部分。
我确定我在各个层面上都误解了各种事情,但希望这里有人可以帮助澄清。谢谢!
内存地址在bytes
,而不是bits
,所以你需要添加1个字节,而不是8位。如您所见,将 8 添加到 BX
将寻址 H
上方的内存 8 bytes
,这将是一个 0
字节(因为您指定 times 510-($-$$) db 0
(现在,用 0
字节填充字节 510。
解决方案:将 1
添加到 BX,而不是 8
(使用 INC BX
可能会更好 - 更快更短)。
btw: mov al,[bx]
意思是'将 BX 指向的 BYTE(即寄存器 BX 中包含的地址)移动到 AL`
db
表示 define BYTE
,而不是 bit
正如用户@Magoo 所说,db
表示 'define byte' 因此要遍历字符串,您需要将指针递增 1 而不是 8。
切勿使用BX作为通过BIOS电传功能输出的文本地址。 BH应该是显示页面参数!!!
在您的代码中它 有效 因为文本 "Hello" 在内存中足够低以至于 BH=0。但这是巧合。
[org 0x7c00]
mov si, Hello
mov ah, 0x0e
Keep_Printing:
mov al, [si]
cmp al, 0
je Finished_Printing
int 0x10
add si, 1
jmp Keep_Printing
Finished_Printing:
cli
hlt
Hello:
db "Hello", 0
times 510-($-$$) db 0
dw 0xAA55