好的,在其他人将此问题标记为重复之前。让我明确指出,这更像是一个调试问题,而不是一个逻辑问题。据我所知,逻辑是正确的,因为如果我在每次操作后单独打印bx
寄存器中的值,那么我得到正确的输出。问题是将结果存储在bx
寄存器中应该更改它所持有的不的内存位置。
所以,这些天我在NASM学习汇编语言。我正在关注pdf文档,要求您打印十六进制数字(将十六进制数字转换为十六进制数字,然后打印)。
我已编写代码,但似乎没有打印正确的十六进制数字。另一方面,如果我只是在以下代码片段中打印变量FINAL_ST
而不调用INIT
(这是十六进制数转换为十六进制字符串的开始),它可以正常工作并打印{{ 1}}。
我多次搜索但无济于事。
我发现gdb可用于调试0x0000
程序,但当输出为nasm
文件时,我无法理解如何使用它。
我还尝试为此代码构建一个控制流图,以了解执行流程但无法找到适合的工具。 :(
代码:
.bin
使用的命令:
[org 0x7c00]
mov ax, 0x19d4
mov bx, FINAL_ST + 5
; jmp PRINTER ; works :/
jmp INIT
NUM:
add dx, 0x0030
mov [bx], dx
jmp CONT
ALPHA:
add dx, 0x0037
mov [bx], dx
jmp CONT
CONT:
dec bx
shr ax, 4
cmp ax, 0x0000
jne INIT
je PRINTER
INIT:
mov dx, 0x000f
and dx, ax
cmp dx, 0x000a
jl NUM
jge ALPHA
;STRING PRINTER
PRINTER:
mov bx, FINAL_ST
mov ah, 0x0e
jmp PRINT ; this doesn't work
PRINT:
mov al, [bx]
int 0x10
inc bx
cmp byte[bx], 0x00
jne PRINT
FINAL_ST:
db "0x0000", 0x00
END:
times 510 - ($ - $$) db 0
dw 0xaa55
nasm boot_hex1.asm -f bin -o boot_hex1.bin
我得到的输出为qemu-system-x86_64 boot_hex1.bin
,而预期输出为0x1
。
答案 0 :(得分:1)
您的问题出现在以下两行:
mov [bx], dx
这会将 DX 中的16位值移动到 BX 中指定的地址。由于x86是小端,因此在循环的每次迭代中都会将 DL 移动到[BX]
并将 DH 移动到[BX+1]
。由于 DH 在代码中始终为零,因此在每个字符写入FINAL_ST
缓冲区后,NUL会终止字符串。
问题在于您真正希望使用 DL 中的字节更新 BX 指向的内存。将两行更改为:
mov [bx], dl
我有bootloader tips的Stackoverflow答案。提示#1是:
当BIOS跳转到您的代码时,您不能依赖具有有效或预期值的CS,DS,ES,SS,SP寄存器。应在引导加载程序启动时正确设置它们。您只能保证您的引导加载程序将从物理地址0x00007c00加载并运行,并且引导驱动器号将加载到DL寄存器中。
至少应将 DS 设置为零,因为您使用的是ORG
(原点)0x7c00。在将控制权转移到引导加载程序之前,您不能假设BIOS将 DS 设置为零。它在 QEMU 中工作,因为它的BIOS恰好在 DS 中具有值0x0000。并非所有硬件和模拟器都能保证这一点。