【问题标题】:Borland c++ inline asm problem with WORD PTR and stringWORD PTR和字符串的Borland c ++内联asm问题
【发布时间】:2010-08-15 16:33:40
【问题描述】:

我正在为 8086 处理器编写小内核(在 BC3.1 中工作,在 Windows XP 上作为主机操作系统)。内核是多线程的,所以当我使用 printf 或 cout 进行调试时会遇到问题(在代码中的某处,printf 将 InterruptEnable 标志设置为 1,并且我的计时器中断例程调用调度并且我的代码发生故障)。

因此,我在内联 asm 中编写了简单的 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”。

我不知道发生了什么。内存模型很大。

【问题讨论】:

  • 你是从定时器 ISR 调用这个? DOS 不可重入。
  • No.. 定时器 ISR 只做上下文切换。我可能有 20 多个线程,并且我也有信号量和事件实现。因此,当我的应用程序挂在某个实施不佳的 wait() 上时,我无法使用调试器对其进行跟踪,我唯一的选择是打印队列大小/元素和代码中的当前行以及线程 ID。但是,如果我使用标准 puts() 执行此操作,我的 Timer ISR 会在 puts 内部的某处被调用,它会导致在没有调试器的情况下运行时没有运行的上下文切换。
  • 很抱歉,除了您的问题之外还问您。我正在使用 Borland Turbo C++ 3。如果我想编写内联汇编程序,我必须在列表中包含什么标题?我的意思是,我必须在#include 上添加什么以使编译器可以理解程序集?我试图只包含 iostream.h、stdio.h、stdlib.h,但没有工作。
  • @AirCraftLover 对不起,我不记得了,上次我这样做是在 10 年前,但是 AFAIK,你不需要包含任何特别的东西 - 这是编译器支持的一部分.也许打开一个新问题并在那里发布一个最小示例(有错误?)。

标签: c++ assembly inline-assembly


【解决方案1】:

首先,至少在我看来,你选择了一个相当糟糕的名字——你的名字几乎是puts,而不是printf。其次,对于您要完成的工作,您可能想尝试使用 Borland 的 cprintfcputs 等——它们使用 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        

【讨论】:

  • 谢谢,成功了!它将仅用于调试而不是其他用途,因此我不在乎函数名称(我发现我错了)。这个 REGS union 似乎很有趣 - 我会检查一下,它似乎非常有用。现在我明白了我在不检查 dos.h 函数时犯了多大的错误。注意:如果有人试图使用 Jerry 的代码,就会漏掉一个 s++。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-10
  • 2015-09-22
  • 1970-01-01
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多