Assembly 程序集:打印时无意中添加十六进制数

Assembly 程序集:打印时无意中添加十六进制数,assembly,x86,nasm,x86-16,bootloader,Assembly,X86,Nasm,X86 16,Bootloader,我想在一个可引导的程序集文件中分别打印两个十六进制数。然而,打印第二个数字似乎会将其添加到第一个数字。正如一些人指出的那样,问题可能出在打印的十六进制部分 这是我的密码: [org 0x7c00] mov dx, [number1] call print_hex mov bx, space call print_string mov dx, [number2] call print_hex jmp $ ; Hang once

我想在一个可引导的程序集文件中分别打印两个十六进制数。然而,打印第二个数字似乎会将其添加到第一个数字。正如一些人指出的那样,问题可能出在打印的十六进制部分

这是我的密码:

[org 0x7c00]

  mov dx, [number1]
  call print_hex  

  mov bx, space
  call print_string

  mov dx, [number2]
  call print_hex

  jmp $                 ; Hang once we're done

print_hex:
  pusha             ; save the register values to the stack for later

  mov cx,4          ; Start the counter: we want to print 4 characters
                    ; 4 bits per char, so we're printing a total of 16 bits

char_loop:
  dec cx            ; Decrement the counter

  mov ax,dx         ; copy bx into ax so we can mask it for the last chars
  shr dx,4          ; shift bx 4 bits to the right
  and ax,0xf        ; mask ah to get the last 4 bits

  mov bx, HEX_OUT   ; set bx to the memory address of our string
  add bx, 2         ; skip the '0x'
  add bx, cx        ; add the current counter to the address

  cmp ax,0xa        ; Check to see if it's a letter or number
  jl set_letter     ; If it's a number, go straight to setting the value
  add byte [bx],7   ; If it's a letter, add 7
                    ; Why this magic number? ASCII letters start 17
                    ; characters after decimal numbers. We need to cover that
                    ; distance. If our value is a 'letter' it's already
                    ; over 10, so we need to add 7 more.
  jl set_letter

set_letter:
  add byte [bx],al  ; Add the value of the byte to the char at bx

  cmp cx,0          ; check the counter, compare with 0
  je print_hex_done ; if the counter is 0, finish
  jmp char_loop     ; otherwise, loop again

print_hex_done:
  mov bx, HEX_OUT   ; print the string pointed to by bx
  call print_string

  popa              ; pop the initial register values back from the stack
  ret               ; return the function

print_string:     ; Push registers onto the stack
  pusha

string_loop:
  mov al, [bx]    ; Set al to the value at bx
  cmp al, 0       ; Compare the value in al to 0 (check for null terminator)
  jne print_char  ; If it's not null, print the character at al
                  ; Otherwise the string is done, and the function is ending
  popa            ; Pop all the registers back onto the stack
  ret             ; return execution to where we were

print_char:
  mov ah, 0x0e    ; Linefeed printing
  int 0x10        ; Print character
  add bx, 1       ; Shift bx to the next character
  jmp string_loop ; go back to the beginning of our loop

; global variables
  HEX_OUT: db '0x0000',0
  number1: dw 1
  number2: dw 2
  space: db " ",0

; Padding and stuff
  times 510-($-$$) db 0
  dw 0xaa55
它给出了输出:

0x0001 0x0003
0x0001 0x0002
我期望输出:

0x0001 0x0003
0x0001 0x0002
编辑:更新了代码和问题陈述,希望使其更加完整和可验证。

因为print\u hex例程在hex\u OUT数据上使用
add byte[bx],al
,它必然取决于hex\u OUT的初始内容

每次使用时只需重置内容:

print_hex:
 pusha 
 mov ax, "00"
 mov [HEX_OUT+2], ax
 mov [HEX_OUT+4], ax
 ...

HEX_OUT: db '0x0000',0

使用调试器检查传递给
print\u hex
dx
。另外,请尝试直接打印
3
以验证
print_hex
是否有效:)我确信
print_hex.asm
与此问题有关。您是否有明确说明寄存器的所有(或大部分)内容都被保留或销毁的函数文档?我看到了include文件(以及
jmp$
),不知道这是否在引导加载程序中?请将此作为一个示例。添加所有代码,包括两个包含文件中的代码,并向我们展示如何构建和运行程序。我必须同意,这似乎是例程
print\u hex
的一些问题。因为我以前做过引导加载程序,所以我以前碰巧有同名的include文件。我起诉他们让一个引导加载程序(添加了一个引导签名和org 0x7c00)运行并工作。使用
org0x100
将其构建为一个DOS COM程序,它也可以工作。如果你自己编码
print_hex
,那么你可能有某种bug。啊,我明白了。非常感谢。我想提高投票率,但我还没有所需的+15声誉。@bjarke15接受后就行了。不取决于您当前的分数。