Search code examples
assemblyx86-16tasm

Order of variable declaration in data segment causes different outputs


I use TASM.

I use this IO.h file for input and output from/to the console. And also for itoa and atoi.

My program is : (The purpose is to simply copy to 20h to 2 memory locations and output both.)

include io.h

data segment
    msg2 db 13, 10, "here it is", 13, 10, 0
    tmp dw ?, 0
    num dw ?, 0
    tmp2 dw ?, 0
data ends
code segment
    assume cs:code, ds:data
    start:
        ;load segments
    mov ax, data
    mov ds, ax

    ;store 20h
    mov ax, 20h
    ;copy to both num and tmp2
    mov num, ax
    mov tmp2, ax

    ;output
    output msg2
            ; (itoa puts the output-able into destination, "tmp" here)
    itoa tmp, tmp2
    output tmp

    ;output
    output msg2
    itoa tmp, num
    output tmp
    ;return control
    mov ax, 4c00h
    int 21h
code ends
    end start

The output I get is :

here it is
32
here it is
12851

However when I make a small change in order of variable definition ( I swap tmp2 and num ):

data segment
    msg2 db 13, 10, "here it is", 13, 10, 0
    tmp dw ?, 0
    tmp2 dw ?, 0
    num dw ?, 0
data ends

The output is :

here it is
32
here it is
32

Can someone explain why this happens? The 2nd output is what I expected in both cases.

p.s : Also, why do we have to use the start label? I find it extremely strange that it extends out of the code segment. It doesn't work correctly without that label.


Solution

  • The io.h you linked only contains a macro that calls the itoa_proc in a library, as such we don't know how that procedure works. It probably uses some extra space, so even through the result (32) fits into 2 bytes, it may be overwriting following memory locations hence destroying your value. Note that 12851 is 0x3233 which in memory looks like 0x33, 0x32 which is just the ascii representation of 32. Just guessing here, but itoa may be producing right-justified output first, then moving it to the left.

    Read the documentation or the source code, if available, or just reserve more space for the output string. I assume for 16 bit numbers 7 bytes should be enough: 1 for possible sign, 5 for the digits, 1 for the terminating zero.