NASM模块将十六进制转换为字符串并打印出来.组装但未按预期工作 [英] NASM module to convert hex into string and print it out. Assembles but not working as expected

查看:151
本文介绍了NASM模块将十六进制转换为字符串并打印出来.组装但未按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个简单的汇编代码,以将十六进制值吐出到屏幕上.有两个与其他模块一起使用的文件print_screen.asm.我认为在尝试将十六进制转换为字符串时,问题出在我的逻辑上.我的代码是:

I am trying to write a simple assembly code to spit out hex values to the screen. There are two files print_screen.asm which is working with other modules. I think the problem is in my logic when trying to convert hex to string. My code is:

[org 0x7c00]

xor dx,dx
xor ax,ax
xor bx,bx

mov dx, 0x1fb6

call print_hex

jmp endi;

print_hex:
    pusha

    mov ax,0x0001
    and ax,dx
    add ah,48
    mov byte [HEX_OUT+5],ah

    mov ax,0x0010
    and ax,dx
    add ah,48
    mov byte [HEX_OUT + 4],ah

    mov ax,0x0100
    and ax,dx
    add ah,48
    mov byte [HEX_OUT + 3],ah

    mov ax,0x1000
    and ax,dx
    add ah,48
    mov byte [HEX_OUT + 2],ah

    mov bx,HEX_OUT
    call print_string

    popa
    ret

jmp endi

%include "print_string.asm"

endi:
;data
HEX_OUT: db '0x0000',0

SAMPLE: db 'a',0
times 510 - ($-$$) db  0
dw 0xaa55

print_screen.asm(与其他模块一起使用):

print_screen.asm (working with other modules):

 print_string:
    pusha
    cld
    mov ah,0x0e

config: mov al,[bx]
    ;Comparing the strings
    cmp byte [bx],0x00  ;Comparing for null
    jne print
    je end

print:  int 0x10
    add bx,1
    jmp config

end:    popa
    ret

推荐答案

mov ax,0x0001
and ax,dx
add ah,48
mov byte [HEX_OUT+5],ah

在上面的代码段中,您只需要保留一位,而您需要保留4位.
当结果肯定在AL中时,您也可以在AH上进行加法.
由于ASCII集的组织方式,您不能仅仅将48转换为十六进制.在'9'(57)的编码和'A'(65)的编码之间存在间隙.您的代码需要解决这个问题!

In the above snippet you only keep a single bit where you need to keep 4 bits.
You also do an addition on AH when the result definitely is in AL.
Because of how the ASCII set is organized, you can't just merily add 48 to convert into the hexadecimal. There is a gap between the encoding for '9' (57) and the encoding for 'A' (65). Your code needs to account for this!

对于最低有效十六进制数字:

For the least significant hex digit:

    mov ax, dx     ;Original number
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + 5], al

对于下一个十六进制,它将变为:

For the next hexdigit this would become:

    mov ax, dx     ;Original number
    shr ax, 4
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + 4], al

对于下一个十六进制,它将变为:

For the next hexdigit this would become:

    mov ax, dx     ;Original number
    shr ax, 8
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + 3], al

对于下一个十六进制,它将变为:

For the next hexdigit this would become:

    mov ax, dx     ;Original number
    shr ax, 12
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + 2], al


这个时间比对我们有利的时间快了很多,因此使用循环会更好.
下一个解决方案将从高端开始,但最终结果不会改变.


This rapidly got longer than is good for us, so using a loop will be much better.
Next solution will start from the high end but the end result will be no different.

    mov bx, 2      ;Position for most significant digit
.Next:
    ror dx, 4      ;Bring digit in lowest 4 bits
    mov al, dl     ;Copy number
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + bx], al
    inc bx
    cmp bx, 6      ;Did we fill chars at +2 +3 +4 +5 ?
    jb  .Next      ;Not yet

因为该循环中有4次迭代,并且每次将DX中的数字旋转4倍,所以DX最终将保留原始值.无需保留它.

Because there are 4 iterations in this loop and the number in DX is rotated 4x each time, DX will hold the original value in the end. No need to preserve it.

jmp endi;

这应该达到什么目的?这正在跳转到 data ,那肯定不是可执行代码!如果您想要一个无限循环,那么只需编写:

What's this supposed to achieve? This is jumping to data and that's certainly not executable code! If you want an endless loop then simply write:

jmp $


您说的另一个文件正在与其他模块一起使用,一团糟!
每个人都忽略了这一点,但是BIOS电传打字功能要求BH寄存器具有所需的显示页面.因此,使用BX作为字符串指针总是一个坏主意.
这是一个很好的解决方案,不需要您更改所有现有代码(关于BX的使用):


The other file, that you say is working with other modules, is a mess!!
Everybody keeps neglecting this, but the BIOS teletype function requires the BH register to have the desired display page. Therefore it's always a bad idea to use BX as the string pointer.
Here's a good solution that doesn't require you to change all of your existing code (concerning the use of BX):

print_string:
    pusha
    mov     si, bx
    mov     bh, 0      ;Display page 0
    ;mov     bl, 7      ;Color if this were a graphical screen
    cld                ;Required to use LODSB correctly
    jmp     .start
  .write:
    mov     ah, 0x0E   ;BIOS.Teletype
    int     0x10
  .start:
    lodsb              ;Increments the pointer automatically
    cmp     al, 0      ;Comparing for null
    jne     .write
    popa
    ret

这篇关于NASM模块将十六进制转换为字符串并打印出来.组装但未按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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