2010-08-15 27 views
3

我正在爲8086處理器編寫小內核(在BC3.1中,在Windows XP上作爲主機操作系統工作)。內核是多線程的,所以當我使用printf或cout進行調試時(在代碼中的某處,printf將InterruptEnable標誌設置爲1,並且我的計時器中斷例程調用了調度並且代碼崩潰),我遇到了問題。Borland C++ inline asm問題,用WORD PTR和字符串

正因爲如此,我在聯彙編寫的簡單puts功能:

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 
    } 


} 

現在,我什麼地方調用它,可以說PCB :: PCB()這樣的:
_printf(「Counstructor PCBA \ n「);
它工作正常。但是,當我將它稱爲其他地方時,在其他字符串的其他文件中輸出例如「tructor PCBa \ n」。

我不知道發生了什麼。內存模型非常龐大。

+0

要調用此從定時器ISR? DOS不可重入。 – 2010-08-15 17:21:28

+0

否定時器ISR只做上下文切換。我可能有20多個線程,並且我也有信號量和事件實現。所以,當我的應用程序掛在一些執行不當的wait()時,我無法使用調試器對其進行跟蹤,我唯一的選擇是在代碼中顯示隊列大小/元素和當前行以及線程ID。但是,如果我使用標準puts()來執行此操作,則我的Timer ISR會在puts內部的某處被調用,並且會導致在沒有調試器的情況下運行時未運行的上下文切換。 – 2010-08-15 19:32:32

回答

2

首先,至少在我看來,你選擇了一個相當可憐的名字 - 你所擁有的幾乎是puts,而不是printf。其次,對於你想要完成的任務,你可能想要嘗試使用Borland的cprintf,cputs等等 - 它們使用DOS控制檯輸出例程,並且他們不允許中斷的可能性相當大。

如果這不起作用,似乎還沒有什麼理由使用內聯彙編。我會做這樣的事情:

// 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++); 
    } 
}    

如果你真的想用匯編語言,我的建議是把它寫的純彙編語言的一個單獨的模塊:

; 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   
+0

謝謝你,工作!它只會用於調試,沒有別的,所以我不在乎函數的名稱(我看到我錯了)。 這個REGS聯盟似乎很有趣 - 我會檢查一下,看起來非常有用。現在我看到我沒有檢查dos.h函數有多大的錯誤。 注:如果有人試圖使用傑裏的代碼,有一個s ++滑倒。 – 2010-08-15 19:27:42

+0

@Burgos:哎呀,很對。我已經添加了增量。 – 2010-08-15 19:40:44