如何用汇编语言在C中生成输入函数

如何用汇编语言在C中生成输入函数,c,inline-assembly,C,Inline Assembly,我正在用OSDEV制作一个操作系统,我想制作一个控制台,但当我使用scanf时,它不起作用。使用此代码将导致无法输入文本。输出为: KironOS控制台-v0.0.1阿尔法之前的版本 键入help,查看命令列表 > Some weird characters > Some weird characters > Some weird characters 这一切还在继续 kernel.c typedef int bool; #define true 1 #define fa

我正在用
OSDEV
制作一个操作系统,我想制作一个控制台,但当我使用
scanf
时,它不起作用。使用此代码将导致无法输入文本。输出为:

KironOS控制台-v0.0.1阿尔法之前的版本
键入
help
,查看命令列表

> Some weird characters

> Some weird characters

> Some weird characters
这一切还在继续

kernel.c

typedef int bool;
#define true 1
#define false 0

#include <stdio.h>

const char* input();
void execute(const char* cmd);
void output(const char* s, bool ln);
void _puts(const char* s);
void _putchar(char c);

char* newline = "\n\r";
char* version = "0.0.1 PRE-ALPHA";

void main(void) {
    output("KironOS Console - v",0); output(version,1);
    output("Type 'help' for a list of commands.",1);
    output("",1);
    while(1==1) {
        output("> ",0);
        execute(input());
        output("",1);
    }
}

void execute(const char* cmd) {
    output(cmd,1);
}

const char* input() {
    // This doesn't work
    const char* inpt = "Hi";
    scanf("%c",&inpt);
    return inpt;
}

void output(const char* s, bool ln) {
    _puts(s);
    if (ln==1) {
        _puts(newline);
    }
}

void _puts(const char* s) {
    while(*s != 0) {
        _putchar(*s);
        s++;
    }
}

void _putchar(char c) {
    __asm {
        mov ah, 0Eh
        mov al, [c]
        mov bh, 0
        mov bl, 0Fh
        int 10h
    }
}
typedef int bool;
#定义真1
#定义false 0
#包括
常量字符*输入();
无效执行(常量字符*cmd);
无效输出(常量字符*s,布尔项次);
void _put(const char*s);
void _putchar(char c);
char*newline=“\n\r”;
char*version=“0.0.1 PRE-ALPHA”;
真空总管(真空){
输出(“KironOS控制台-v”,0);输出(版本1);
输出(“键入命令列表的“帮助”,1);
输出(“,1);
而(1==1){
输出(“>”,0);
执行(输入());
输出(“,1);
}
}
无效执行(常量字符*cmd){
输出(cmd,1);
}
常量字符*输入(){
//这不管用
常量字符*inpt=“Hi”;
scanf(“%c”、&inpt);
返回输入;
}
无效输出(常量字符*s,布尔项次){
_卖出(s);
如果(ln==1){
_puts(换行符);
}
}
void\u put(常量字符*s){
而(*s!=0){
_putchar(*s);
s++;
}
}
void_putchar(字符c){
__asm{
mov啊,0Eh
mov al[c]
莫夫波黑,0
mov bl,0Fh
int 10h
}
}
编辑: 根据评论,

C语言中的
putchar
函数是:

void _putchar(char c, int *column) {
    char *start;
    start = (char *)0xb8000;
    char *loc;
    loc = start + ((*column) * 2); //Two bytes per cell: one for the char, other for color
    *loc = c;
    *column += 1;
}

这是假设您使用的是80*25文本模式。

正如您在评论中所指出的,您的输入例程不起作用。它有几个问题

const char* inpt = "Hi";
scanf("%c",&inpt);
这段代码的目的似乎是创建一个可以接受字符串的缓冲区,但如果是这样,缓冲区的长度就只能容纳两个字符的字符串。(实际上有3个字符,“H”、“i”和0。)

快速浏览一下scanf的文档就会发现,在格式说明符之后传递的参数需要与指定的类型匹配。在你的情况下,这是一个单一的字符。因此,您应该传递一个字符的地址,换句话说,就是一个
char*
。但是你实际上是在传递一个
char*
的地址,我不知道为什么你的编译器没有警告你(甚至产生错误)。我的孩子不会让我犯那样的错误

所以这应该行得通

char inpt[2] = {0,0};
scanf("%c",inpt);
。。。假设您一次只能输入一个字符,并希望将其视为字符串但是
输入
函数返回局部变量的地址是不安全的。可以返回单个字符,也可以将缓冲区的地址传递到函数中,然后函数可以写入缓冲区

如果您的意图是输入整个字符串并对其执行操作,那么您可能需要以下内容:

char str [80];
scanf ("%79s",str);

如果您使用的是
gcc
,则内联汇编代码应为
GAS
格式,而不是
Intel
格式。@SusmitAgrawal:
\u asm{block}
不是gcc语法;它是MSVC,或者可能是
clang-fasm blocks
。它是用wcl编译的,我想那是WATCOM。我还必须根据我遵循的教程安装,而不是gcc
wcl-lr-l=COM-0-fe=KERNEL.COM KERNEL.c
。您没有包括您的定义
scanf
;如果静态链接32位或64位
libc
定义,那么它当然不能在独立内核中工作。如果正常定义了
scanf
,则将用字符覆盖指针值的一个字节。(不是指向字符串的文字,您可能可以在没有内存保护的情况下在实模式下修改它,即使您告诉编译器它是
const
scanf(“%c”,inpt)
)@PeterCordes:默认的DOS Watcom c库依赖于DOS中断(int 0x21),尽管有一些C库函数的BIOS变体。例如,
\u bprintf
,不幸的是,
putchar
的部分操作是增加输出位置。你忘了做那件事。使用
静态
变量或其他东西。或者将其定义为
putchar\u col(char c,int col)
,但不要使用全局
col\u编号,这是一种糟糕的风格。我的旧的_putchar函数比这个函数工作得更好,这只会给我错误你会得到什么错误?您可能需要修改编译器标志以删除它们。根据错误,您似乎已经使用了我在这里给出的变量名称Z(可能在
stdio.h
?)。您需要更改变量名称,并将适当的参数传递给函数。您可以在此项目中查看my
display.c
display.h
char Input[2]
是一个局部变量:您无法安全地返回它<代码>静态字符输入[80]
会有意义,但不会自动存储。OP使用非常旧的Watcom编译器生成16位二进制文件。显然,它并没有关于格式字符串与类型不匹配的警告。将错误类型传递给变量函数不是编译时错误,这是C++通常避免打印和扫描的原因之一。