问题
OK, before someone else marks this question as a duplicate. Let me make this very clear that this is more of a debugging problem than a logical problem. The logic is correct as far as I know because if I individually print the value in bx
register after each operation, then I get correct output. The problem is that storing the results in bx
register should make changes in the memory location it holds which is not happening.
So, I was learning assembly language these days, in NASM. I am following a pdf document which asks you to print a hexadecimal number (convert hex number to hex string and then print it).
I've written the code but it doesn't seem to print the correct hex number. On the other hand if I just print the variable FINAL_ST
in the following code snippet without calling INIT
(which is the start of the conversion of hex number to hex string), it works fine and prints 0x0000
.
I've searched multiple times but to no avail.
I found out that gdb can be used to debug nasm
programs but I could not understand how to use it when the output is a .bin
file.
And I also tried constructing a Control Flow Graph for this code to understand execution flow but could not find an appropriate tool for it. :(
Code:
[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
Commands used:
nasm boot_hex1.asm -f bin -o boot_hex1.bin
qemu-system-x86_64 boot_hex1.bin
I get the output as 0x1
while the expected output is 0x19D4
.
回答1:
Your issue is on the two lines that look like this:
mov [bx], dx
This moves the 16-bit value in DX to the address specified in BX. Since x86 is little endian this has the effect of moving DL to [BX]
and DH to [BX+1]
on each iteration of your loop. Since DH is always zero in your code this has the effect of NUL terminating the string after each character is written to the FINAL_ST
buffer.
The problem is that you are really looking at updating memory pointed to by BX with the byte in DL. Change both lines to be:
mov [bx], dl
I have a Stackoverflow answer with bootloader tips. Tip #1 is:
When the BIOS jumps to your code you can't rely on CS,DS,ES,SS,SP registers having valid or expected values. They should be set up appropriately when your bootloader starts. You can only be guaranteed that your bootloader will be loaded and run from physical address 0x00007c00 and that the boot drive number is loaded into the DL register.
At a minimum you should set DS to zero since you are using an ORG
(origin point) of 0x7c00. You can't assume the BIOS will set DS to zero before transferring control to your bootloader. It works in QEMU since its BIOS happens to have the value 0x0000 in DS already. Not all hardware and emulators will guarantee this.
来源:https://stackoverflow.com/questions/47589166/convert-hexadecimal-number-to-hexadecimal-string-in-assembly-language-nasm-de