tags:

views:

114

answers:

1

Hello,

I am writing small kernel for the 8086 processor (Working in BC3.1, on Windows XP as host operating system). Kernel is multithreaded, so I have problems when I use printf or cout for debugging (somewhere in code, printf sets InterruptEnable flag to 1, and my timer interrupt routine calls dispatch and my code breaks down).

Because of that, I wrote simple puts function in inline asm:

void _printf(char *c)
{
    //setup data
    asm{
        mov ch, 10
        mov cl, 0
        mov ah, 0x2
        mov bx, WORD PTR c
    }

    loop: asm{
              //\0?
              cmp [bx], cl
              je exit_prc
              mov dl, [bx]
              int 0x21
              inc bx
              //is there \n?
              cmp [bx], ch
              je newline

              jmp  loop
    }
    exit_prc: return;
    newline: asm{
                //insert cr char
                mov dl, 0xD
                int 21h
                jmp loop
    }


}

Now, I call it somewhere in, lets say PCB::PCB() like this:
_printf("Counstructor PCBa\n");
and it works fine. However, when I call it somewhere else, in some other file with other string it outputs for example "tructor PCBa\n".

I don't have a clue what is going on. Memory model is huge.

+2  A: 

First of all, at least in my opinion, you've chosen a rather poor name -- what you have is pretty much a puts, not a printf. Second, for what you're trying to accomplish, you might want to try using Borland's cprintf, cputs, and such -- they use the DOS console output routines, and there's a pretty decent chance they don't enable interrupts.

If that won't work, there still seems to be little reason to use inline assembly. I'd do something like this:

// warning: untested -- and it's been a while since I wrote any code like this, 
// so it's probably a little wrong.
//
void myputc(char ch) { 
    union REGS in, out;

    // set up registers here:
    in.h.ah = 2;

    in.h.dl = ch;
    intdos(&in, &out);
}

void myputs(char huge *s) { 
    while (*s) { 
        if (*s == '\n')
            myputc('\r');
        myputc(*s++);
    }
}            

If you really want to use assembly language, my advice would be to write it as a separate module of pure assembly language:

; Again: not tested and I haven't done this in a while, so use with care.
;
.model large, c

.code

LF = 10
CR = 13

putc proc
    mov dl, al
    mov ah, 2
    int 21h
    ret
putc endp

puts proc string: ptr char
    mov si, string
    lodsb
next:
    cmp al, LF
    jnz printit
    mov dl, CR
    mov ah, 2
    int 21h
printit:
    mov dl, al
    mov ah, 2
    int 21h
    lodsb
    test al, al
    jnz next
    ret
puts endp
    end        
Jerry Coffin
Thank you, that worked! It will be only used for debugging and for nothing else, so I didn't care about function name (and I see I got wrong). This REGS union seems to be interesting - I will check it out, it seems very useful. Now I see how big mistake I made not checking dos.h functions.Note: if somebody is trying to use Jerry's code, there is one s++ slipped.
Burgos
@Burgos: oops, quite right. I've added the increment.
Jerry Coffin