【发布时间】:2019-07-03 17:25:46
【问题描述】:
我正在尝试编写一个简单的操作系统,但无法将十六进制数字转换为字符串。我写了一个字符串打印机,如果我在一些预定义的字符串上调用它,它工作正常。但是在将十六进制数字转换为字符串后,它会打印数字,但下一次调用打印机会在同一行打印所有内容,在某些设置中甚至会打印奇怪的字符。
我使用 NASM 生成代码,使用 Bochs 来模拟 x86 CPU。
[org 0x7c00] ;tell nasm add the adress, specified by org to the relative adresses of the code
mov bx, helloMsg
call stringPrinter
mov dx, 0xde3f
call hexPrinter
mov bx, byeMsg
call stringPrinter
mov bx, newLine
call stringPrinter
mov bx, testMsg
call stringPrinter
jmp end
%include "src/asm/printer.asm"
%include "src/asm/hexParser.asm"
helloMsg:
db 'Hello, World!', 0xa, 0xd , 0
byeMsg:
db 'Bye Bye!', 0xa, 0xd, 0
testMsg:
db 'this is a test', 0xa, 0xd, 0
newLine:
db 0xa, 0xd
end:
jmp $
times 510-($-$$) db 0 ; pad with zeros until the 510th byte of the sector is reached
dw 0xaa55
stringPrinter:
pusha
mov ah,0x0e ; tele output
start:
mov al, [bx]
cmp al, 0x0
je stop
int 0x10 ; interupt 10 for screen printing
inc bx
jmp start
stop:
popa
ret
charPrinter:
push ax
mov ah,0x0e ; tele output
mov al, bl
int 0x10
mov al, 0xa
int 0x10
mov al, 0xd
int 0x10
pop ax
ret
hexPrinter:
pusha
call hexToString
mov bx, ax
call stringPrinter
popa
ret
hexToString:
push bx
push dx
mov bx, output
mov ax, dx
shr ax, 12
call determineValue
add bx, 2
mov [bx], ax
mov ax, dx
and ax, 0x0f00
shr ax, 8
call determineValue
inc bx
mov [bx], ax
mov ax, dx
and ax, 0x00f0
shr ax, 4
call determineValue
inc bx
mov [bx], ax
mov ax, dx
and ax, 0x000f
call determineValue
inc bx
mov [bx], ax
mov ax, output
pop dx
pop bx
ret
determineValue:
cmp ax, 0x0
je zeroDigit
cmp ax, 0x1
je oneDigit
cmp ax, 0x2
je twoDigit
cmp ax, 0x3
je threeDigit
cmp ax, 0x4
je fourDigit
cmp ax, 0x5
je fiveDigit
cmp ax, 0x6
je sixDigit
cmp ax, 0x7
je sevenDigit
cmp ax, 0x8
je eightDigit
cmp ax, 0x9
je nineDigit
cmp ax, 0xa
je aDigit
cmp ax, 0xb
je bDigit
cmp ax, 0xc
je cDigit
cmp ax, 0xd
je dDigit
cmp ax, 0xe
je eDigit
cmp ax, 0xf
je fDigit
zeroDigit:
mov ax, '0'
ret
oneDigit:
mov ax, '1'
ret
twoDigit:
mov ax, '2'
ret
threeDigit:
mov ax, '3'
ret
fourDigit:
mov ax, '4'
ret
fiveDigit:
mov ax, '5'
ret
sixDigit:
mov ax, '6'
ret
sevenDigit:
mov ax, '7'
ret
eightDigit:
mov ax, '8'
ret
nineDigit:
mov ax, '9'
ret
aDigit:
mov ax, 'a'
ret
bDigit:
mov ax, 'b'
ret
cDigit:
mov ax, 'c'
ret
dDigit:
mov ax, 'd'
ret
eDigit:
mov ax, 'e'
ret
fDigit:
mov ax, 'f'
ret
output:
db '0x0000' , 0
【问题讨论】:
-
你没有 NUL 终止你的
newLine字符串。它应该是db 0xa, 0xd, 0x0。最终结果是打印 0x0a、0x0d 之后内存中的内容,这就是您看到的垃圾。 -
哦,现在它工作得多么愚蠢。但这实际上只是一种解决方法。最初我将 0xa, 0xd, 0 放在 hexParser.asm 文件末尾的“输出”变量后面。在没有“换行符打印”的情况下执行此操作会生成以下输出:Hello, World!\n0xde3fBye Bye!\n这是一个测试\n 现在数字和再见消息在同一行,我不明白为什么会这样.
-
NASM 仅处理反引号内的 C 样式转义序列,而不是单引号或双引号。 nasm.us/doc/nasmdoc3.html#section-3.4.2 所以如果你想使用
foo\n,你必须把它放在反引号里面。 -
抱歉,这是个误会。我是新来的,在这个评论编辑器中发布代码不允许我在不同的行上输入和写东西。 “\n”转义序列仅代表不同的代码行......我实际上并没有在我的汇编文件中编写它们。如果我不在这里写但在“回答你的问题”部分,也许它会起作用......?
-
顺便说一句,整个
determineValue例程可以替换为cmp ax, 10jae hexdigitadd ax, '0'rethexdigit:add ax, 'a' - 10ret。
标签: assembly x86 nasm x86-16 bootloader