用汇编语言(NASM)将十六进制数转换为十六进制字符串(调试) [英] Convert hexadecimal number to hexadecimal string in assembly language (NASM) (debug)

查看:576
本文介绍了用汇编语言(NASM)将十六进制数转换为十六进制字符串(调试)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,在其他人将此问题标记为重复之前.让我非常清楚地表明,这更多是调试问题,而不是逻辑问题.据我所知,逻辑是正确的,因为如果我在每次操作后分别打印bx寄存器中的值,那么我将获得正确的输出.问题在于,将结果存储在bx寄存器中应该更改其保存的存储位置,而这不会发生.


这些天来,我在NASM学习汇编语言.我正在查看一个pdf文档,该文档要求您打印一个十六进制数字(将十六进制数字转换为十六进制字符串,然后打印出来).

我已经编写了代码,但是它似乎无法打印正确的十六进制数字.另一方面,如果我仅在以下代码段中打印变量FINAL_ST而不调用INIT(这是将十六进制数字转换为十六进制字符串的开始),则它可以正常工作并打印0x0000.

我已经搜索了多次,但无济于事.

我发现gdb可用于调试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,而预期的输出为0x19D4.

解决方案

问题出在以下两行中:

mov [bx], dx

这会将 DX 中的16位值移动到 BX 中指定的地址.由于x86是小字节序,因此在循环的每次迭代中都会将 DL 移至[BX],将 DH 移至[BX+1].由于 DH 在您的代码中始终为零,因此在将每个字符写入FINAL_ST缓冲区后,NUL会终止字符串.

问题是您实际上正在使用 DL 中的 byte 来更新 BX 指向的内存.将两行都更改为:

mov [bx], dl


我有一个Stackoverflow答案,其中包含引导程序提示.提示1是:

BIOS跳转到您的代码时,您不能依赖具有有效或预期值的CS,DS,ES,SS,SP寄存器.引导加载程序启动时,应适当设置它们.您只能保证引导加载程序将从物理地址0x00007c00加载并运行,并且引导驱动器号已加载到DL寄存器中.

由于使用的ORG(起点)为0x7c00,因此至少应将 DS 设置为零.在将控制权转移到引导加载程序之前,不能假设BIOS将 DS 设置为零.它可以在 QEMU 中使用,因为它的BIOS在 DS 中已经具有值0x0000.并非所有的硬件和仿真器都可以保证这一点.

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.

解决方案

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.

这篇关于用汇编语言(NASM)将十六进制数转换为十六进制字符串(调试)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆