0

So, I'm figuring out Assembly by writing a function that prints a hexadecimal number. How function works: in a loop, it gets the last digit of a number, converts it to a char, and replaces char at HEX_OUT string (HEX_OUT: DB "0x0000", 0, so the function is going to rewrite each char to make the corresponding number), and then repeat it until the number will be mapped to the HEX_OUT string, and then it prints it.

But there's a problem with registers that I don't understand. The problem is that when I put some value into ax register (say, 6), and then place the value of ax into bx register (mov [bx], ax), at the end of the day I get 0x1 printed on my screen, but if I change the instruction to mov [bx], al, I get 0x1fb6 (assuming that the number to be printed is 0x1fb6, it's correct result).

As far as I know about registers, since I placed 6 in ax, al register should be equal to the value of ax.

Please, look at the comment line with [HERE], this where the problem is.

; 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

print_string function (I don't think there's any problems with it):

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             
  • 5
    `mov [bx], ax` is writing 2 bytes. So it's overwriting an extra byte that you probably did not intend to. – Jester Sep 11 '20 at 23:33
  • 2
    Note that you can generate digits in printing order (so you can loop forward instead of backward over the buffer) by rotating left, starting with the top nibble. [How to convert a binary integer number to a hex string?](https://stackoverflow.com/q/53823756) shows how. That makes it easier to use simpler indexing, fewer instructions in the loop. Or since you're using 1 char at a time printing, you could just inline the printing into the digit loop. Also, never `jcc` over a `jmp`, just `jng next` or fall through into the `add al, 'a'-10 - '0'`. – Peter Cordes Sep 11 '20 at 23:53
  • @Jester But why is it overwriting? I mean, both `bx` and `ax` are of the same size, everything should be okay, isn't it? Could you please elaborate on it. – thedenisnikulin Sep 12 '20 at 19:05
  • 1
    It's a write to memory. The size of `bx` is irrelevant. – Jester Sep 12 '20 at 19:08
  • @Jester could you please recommend me an article about registers or something, because I still don't quite understand how they work and why it's a write to memory :( – thedenisnikulin Sep 12 '20 at 19:40
  • 1
    The brackets `[]` make it a memory reference. `mov bx, ax` would be a transfer between registers, `mov [bx], ax` is a write into memory at address `bx`. – Jester Sep 12 '20 at 19:55
  • @Jester Thanks, this is pretty understandable, but why it gets overwritten? – thedenisnikulin Sep 12 '20 at 21:20
  • 1
    An extra byte in memory gets overwritten. I haven't traced what exactly that causes in your code, but if it works with `al` then surely that is the problem. – Jester Sep 12 '20 at 21:42

0 Answers0