首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用程序集中的getchar的get()函数

使用程序集中的getchar的get()函数
EN

Stack Overflow用户
提问于 2018-09-03 04:25:03
回答 1查看 1.4K关注 0票数 1

我在为我的一个类编写的C代码上编写gets()函数时遇到了一些问题。所以我已经有了一个getchar()函数,但是在汇编上,我用extern从C中调用它,问题是,在我运行代码的时候,我输入了一个字符串,它没有显示完整的字符串,而是一些字符。

这是我的ATM机代码:C代码:

代码语言:javascript
复制
extern char getchar(void);
extern void putchar(char data);
void gets(char *str);
void puts(char *str);
void new_line();

char string[20];

int main(){
    while(1){
        gets(string);
        new_line();
        puts(string);
    }
    return 0;
}

void new_line(){
    putchar(0xD);
    putchar(0xA);
}
void gets(char *str){
    unsigned char i = 0;
    while((*str = getchar()) != 0xD){
        str[i] = getchar();
        i++;
    }
}

void puts(char *str){
    while(*str){
        putchar(*str++);
    }
}

和我的ASM代码以防万一:

代码语言:javascript
复制
.MODEL tiny

.CODE
    public _putchar
    public _getchar

    _putchar    PROC
                push bp
                mov bp, sp
                mov dl, [bp + 4]
                mov ah, 2
                int 21h
                pop bp
                ret
    _putchar    ENDP

    _getchar    PROC
                push bp
                mov bp, sp
                mov ah, 1
                int 21h
                mov [bp + 4], al
                pop bp
                ret
    _getchar    ENDP
END

我在Arduino Mega上运行代码,使用MTTTY和我们老师提供的8086解释器。

有什么办法可以用get()函数解决这个问题,这样我就可以正确地显示输入字符串了吗?

例如,如果我输入"hello world“,它只打印"l ol”。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-03 04:41:09

无论gets 实现如何,您的C gets实现都已损坏。你可以用桌面上的普通调试器在普通的C实现上调试它。

您调用getchar()两次,并且每隔一次结果才保存一次。

第一个结果被分配给str[0]并检查'\r'

代码语言:javascript
复制
// your version with comments
void gets_original_buggy (char *str){
    unsigned char i = 0;   // this is an index; it should be an `int` or `size_t`

    while((*str = getchar()) != 0xD){  // overwrite the first byte of the string with an input
        str[i] = getchar();    // get ANOTHER new input and save it to the end.
        i++;
    }
    // str[i] = 0;  // missing zero terminator.
}

我是这样写的:

代码语言:javascript
复制
#include <stddef.h>
//#include <stdio.h>

extern unsigned char getchar(void);

// returns length.
// negative means EOF.  TODO: implement an EOF check if your getchar() supports it.
// FIXME: take a max-length arg to make it possible to prevent buffer overflows.
ptrdiff_t gets(char *str) {
    char *start = str;  // optional

    char tmp;  // read chars into a local, and check before assigning anything to *str
    while( (tmp = getchar()) != '\r') {
        // TODO: also check for EOF
        *str++ = tmp;            // classic pointer post-increment idiom
    }
    *str = 0;     // terminate the C string.

    return str - start;  // optional, return the length
}

返回字符串长度总是有用的,而不是在知道它的函数中丢弃它,这只需要编译器额外的几条指令。指针增量简化了寻址模式,节省了代码大小。

(用gcc and clang for 32-bit x86 on Godbolt编译得很好,应该与x86-16非常相似。)

您还可以根据您的getchar实现检查'\n',以及它是否规范化了行结束。请记住,如果你有DOS \r行结尾,那么在读取\n之后停止将会留下一个未读的"\r\n"

在ISO中,对于以文本模式打开的文件,getchar()应该只为您提供'\n'行结尾,但是您已经使getchar只是DOS (从标准输入读取字符,带回显)函数的包装器。因此,这就是设置实现行为的原因。

asm错误:

代码语言:javascript
复制
# in _getchar:
    mov [bp + 4], al         ; clobber memory you don't own.

这将占用返回地址上方的内存。char getchar(void)不接受任何参数,因此您的函数并不“拥有”该内存。你的编译器应该期望一个AL的返回值。(如果你认为这是通过引用返回的,不,你只是覆盖了指针arg。除了调用者甚至没有传递一个。)

如果您希望您的getchar能够返回不同于0xFF字节的EOF,请在进行系统调用后将其声明为返回int,并将AH声明为零。(因此,您可以在AX中返回一个16位的值,或者在AX中返回一个零扩展的unsigned char (即AL中的值)。

顺便说一句, 和在ISO 中删除了是有原因的:在读取未知长度的输入时,不可能防止缓冲区溢出。

你的函数应该接受一个大小限制作为第二个参数。

直接对Arduino的AVR或ARM CPU编程可能比在仿真的8086上使用DOS系统调用更容易学习,也更有用。如果你打算这样做,那么在真实的硬件和模拟器上做这件事是没有意义的。

学习x86作为你的第一种汇编语言是没问题的,如果你不去折腾分段,并且你不想写一个引导加载程序( A20门有很多神秘的遗留东西,并且从实模式切换到保护模式)。除了维护遗留代码库之外,DOS系统调用完全过时了。了解不同的AH=??/ int 21h系统调用是如何工作的细节与COBOL语言一样有用。如果你正在创建一个传统的引导扇区(而不是int 10h ),那么BIOS和其他系列会稍微有用一些,但是你不需要这样做来学习asm。如果您在Linux、Windows、Mac、*BSD或其他平台上的用户空间中学习asm,那么以后如果您需要了解/学习其他与外部世界通信的方式,并了解内核如何工作,就会变得很容易。

Linux系统调用具有类似的ABI (eax=call number / int 0x80sysentersyscall),但是Linux系统调用或多或少都是POSIX系统调用,了解它们对于实际的低级编程非常有用。

使用sys_read的POSIX TTY行缓冲输入的复杂性不同于DOS字符读取函数和行结束废话的复杂性,但可以说学习起来更有用。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52140756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档