Assembly NASM模块将十六进制转换为字符串并打印出来。组装但未按预期工作
我试图编写一个简单的汇编代码,将十六进制值输出到屏幕上。有两个文件Assembly NASM模块将十六进制转换为字符串并打印出来。组装但未按预期工作,assembly,x86,nasm,bootloader,Assembly,X86,Nasm,Bootloader,我试图编写一个简单的汇编代码,将十六进制值输出到屏幕上。有两个文件print\u screen.asm正在与其他模块一起使用。我想问题出在我尝试将十六进制转换为字符串时的逻辑上。我的代码是: [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,4
print\u screen.asm
正在与其他模块一起使用。我想问题出在我尝试将十六进制转换为字符串时的逻辑上。我的代码是:
[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
打印屏幕.asm
(使用其他模块):
在上面的代码片段中,您只保留了需要保留4位的一位。当结果肯定在
AL
中时,您还可以在AH
上进行添加由于ASCII集合是如何组织的,所以不能简单地将48相加以转换为十六进制。“9”(57)的编码与“a”(65)的编码之间存在差距。你的代码需要考虑到这一点 对于最低有效十六进制数字:
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
对于下一个六位数,这将成为:
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
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
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
对于下一个六位数,这将成为:
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
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
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
对于下一个六位数,这将成为:
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
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
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
这对我们来说很快就变得很长了,所以使用循环将更好。
下一个解决方案将从高端开始,但最终结果不会有什么不同
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
最终将保持原始值。没有必要保存它
这应该达到什么目的?这是跳转到数据,这肯定不是可执行代码!如果您想要一个无止境的循环,只需写下:
jmp $
另一个文件,你说是与其他模块一起工作的,是一团混乱
每个人都忽略了这一点,但BIOS电传打字功能要求
BH
寄存器具有所需的显示页面。因此,使用BX
作为字符串指针总是一个坏主意。这里有一个很好的解决方案,它不需要您更改所有现有代码(关于使用
BX
):
在堆栈溢出的俄文端有一段代码,用于将十六进制字节转换为更干净的字符串。以下是片段:
mov bh, 0x00
mov bl, ah
shr bl, 0x04
mov al, [bx+hex_nums]
mov [error_code_hex], al
and ah, 0x0F
mov bl, ah
mov ah, [bx+hex_nums]
mov [error_code_hex+1], ah
hex_nums: db "0123456789ABCDEF"
错误代码是它打印十六进制字符的地方。它基本上以4位作为序列来引用ASCII十六进制序列的字节。有人做过这项工作吗?你一次只能屏蔽1位,而不是4位。另外,您将其保留在原位。当您执行
mov ax,0x0010;和ax,dx
?给一个例子加上一些值,看看结果是什么。@Jester我得用F.Dang愚弄我。谢谢。事实上,这些价值观也在不断变化。再次感谢。@Jester我可以使用循环吗??如果可能,如何向十六进制输出标签添加偏移量。是的,可以使用循环。您可以执行类似于[HEX\u OUT+bx]
的操作,并且在shr al,4
之前,0xF0
是冗余的。被屏蔽的比特即将被移出。使用AL而不是执行mov-bl,ah
/shr-bl,4
,保存mov-bl,AL
指令也是毫无意义的。这样更好。你说“有人成功了吗?”是什么意思?你想问一个新问题吗?将AH转换为2位十六进制字符串看起来完全正常。除了hex\u nums:
不能与代码对齐,否则这16个字节将被解码为指令!。您需要将查找表放在它自己的部分中,或者放在其他代码之后。@PeterCordes如果您在代码部分之前跳转,您可以将它放在代码部分。@Ачччаааааачаааааааа107。这段代码没有做到。我确实提到了另一节中的“其他代码之后”选项。相关: