Assembly 与AX和AL寄存器混淆
所以,我通过编写一个打印十六进制数的函数来计算汇编。 函数工作原理:在循环中,它获取数字的最后一位,将其转换为字符,并在Assembly 与AX和AL寄存器混淆,assembly,x86,nasm,cpu-registers,Assembly,X86,Nasm,Cpu Registers,所以,我通过编写一个打印十六进制数的函数来计算汇编。 函数工作原理:在循环中,它获取数字的最后一位,将其转换为字符,并在HEX\u OUT字符串处替换字符(HEX\u OUT:DB“0x0000”,0,因此函数将重写每个字符以生成相应的数字),然后重复该操作,直到数字映射到HEX\u OUT字符串,然后打印出来 但我不明白寄存器有个问题。 问题是,当我将一些值放入ax寄存器(比如,6)中,然后将ax的值放入bx寄存器(mov[bx],ax),一天结束时,屏幕上会打印0x1,但如果我将指令更改为m
HEX\u OUT
字符串处替换字符(HEX\u OUT:DB“0x0000”,0
,因此函数将重写每个字符以生成相应的数字),然后重复该操作,直到数字映射到HEX\u OUT
字符串,然后打印出来
但我不明白寄存器有个问题。
问题是,当我将一些值放入ax
寄存器(比如,6
)中,然后将ax
的值放入bx
寄存器(mov[bx],ax
),一天结束时,屏幕上会打印0x1
,但如果我将指令更改为mov[bx],al
,我得到了0x1fb6
(假设要打印的数字是0x1fb6,这是正确的结果)
就我所知,由于我在ax
中放置了6
,al
寄存器应该等于ax
的值
请查看带有[此处]
的注释行,这就是问题所在
; HEX_OUT ("0x0000") is stored in bx
; hexadecimal number to be printed (0x1fb6) is stored in dx
print_hex:
pusha
mov cx, 0 ; cx = counter
loop1:
cmp cx, 4 ; if counter < 4
jl print ; jump to print
jmp end ; else jump to end
print:
mov ax, dx ; ax = 0x1fb6
and ax, 0x000f ; ax = 6
cmp ax, 9 ; if ax > 9
jg num_to_abc ; make a letter out of char (because hexadecimal)
jmp next ; jump to next
num_to_abc:
add ax, 39
jmp next
next:
add ax, '0' ; make a char out of num
mov bx, HEX_OUT + 5 ; bx now points to last char of string
sub bx, cx ; bx = bx - counter
mov [bx], al ; [HERE] al is currently 54 (6 + '0'). But why al works properly, but ax doesn't?
ror dx, 4 ; put last digit at the beginning (before: 0x1fb6, after: 0x61fb)
inc cx ; counter++
jmp loop1 ; jump back to loop
end:
mov bx, HEX_OUT ; some code
call print_string
popa
ret
mov[bx],ax正在写入2个字节。因此,它覆盖了一个您可能不打算覆盖的额外字节。请注意,您可以通过从上半字节开始向左旋转来按打印顺序生成数字(这样您可以在缓冲区上向前而不是向后循环)。展示了如何。这使得使用更简单的索引更容易,循环中的指令更少。或者,由于一次打印使用1个字符,您可以将打印内容内联到数字循环中。此外,决不要在jmp
上使用jcc
,只需jngnext
或进入addal,'a'-10-'0'
。这是对内存的写入。bx
的大小是不相关的。括号[]
使其成为内存引用mov bx,ax
将是寄存器之间的传输,mov[bx],ax
是在地址bx
处写入内存。内存中的额外字节将被覆盖。我还没有在你的代码中找到确切的原因,但是如果它与al
一起工作,那肯定是问题所在。
print_string:
pusha
mov ah, 0x0e
loop:
mov al, [bx]
cmp al, 0
je return
jmp put_char
put_char:
int 0x10
inc bx
jmp loop
return:
popa
ret