NASM模块将十六进制转换为字符串并打印出来.组装但未按预期工作 [英] NASM module to convert hex into string and print it out. Assembles but not working as expected
问题描述
我正在尝试编写一个简单的汇编代码,以将十六进制值吐出到屏幕上.有两个与其他模块一起使用的文件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屋!