使用 INT 21h (DOS) 和 8086 汇编语言读取数字

3

我需要提示用户输入一个数字,然后存储这个数字并对它进行一些操作。在搜索了INT 21h之后,我找到了以下内容:

INT 21h / AH=1 - read character from standard input, with echo, result is stored in AL.
if there is no character in the keyboard buffer, the function waits until any key is pressed. 

example:

    mov ah, 1
    int 21h

这个问题在于它只读取一个字符并将其表示为ASCII码。因此,如果我需要写数字“357”,我会将其读取为3、5、7。但这不是我的目的。有什么建议吗?

如果您需要读取三个字符,则必须将读取一个字符的调用放入循环中,直到您获得所需的三个字符为止。 - Pete Wilson
@PeteWilson 我需要将整个数字作为“整体”来读取,这样我才能对它进行加法等操作...等等 - xsari3x
2个回答

4

当你成功获取用户输入时,将其指针放入ESI寄存器中(ESI = 字符串地址)

.DATA
myNumber BYTE "12345",0        ;for test purpose I declare a string '12345'

Main Proc
    xor ebx,ebx                ;EBX = 0
    mov  esi,offset myNumber   ;ESI points to '12345'

loopme:

    lodsb                      ;load the first byte pointed by ESI in al

    cmp al,'0'                 ;check if it's an ascii number [0-9]
    jb noascii                 ;not ascii, exit
    cmp al,'9'                 ;check the if it's an ascii number [0-9]
    ja noascii                 ;not ascii, exit

    sub al,30h                 ;ascii '0' = 30h, ascii '1' = 31h ...etc.
    cbw                        ;byte to word
    cwd                        ;word to dword
    push eax
    mov eax,ebx                ;EBX will contain '12345' in hexadecimal
    mov ecx,10
    mul ecx                    ;AX=AX*10
    mov ebx,eax
    pop eax
    add ebx,eax
    jmp loopme                 ;continue until ESI points to a non-ascii [0-9] character
    noascii:
    ret                        ;EBX = 0x00003039 = 12345
Main EndP

使用imul ebx, eax, 10,而不是那笨拙的push/mul操作。此外,如果需要的话,请使用movsx eax, [esi],或者更好的方法是像NASM Assembly convert input to integer?中所示进行零扩展。 - Peter Cordes

2

一旦你得到了字符串,你必须将其转换为数字。问题是,你必须编写自己的过程来完成这个任务。这是我通常使用的一个(虽然是用C语言编写的):

int strToNum(char *s) {
    int len = strlen(s), res = 0, mul = 0;
    char *ptr = s + len;

    while(ptr >= s)
        res += (*ptr-- - '0') * (int)pow(10.0, mul++);

    return res;
}

这是解释。首先,*ptr-- - '0'获取数字的整数表示(例如'9' - '0' = 9),然后它将ptr递减,以便它指向前一个字符。一旦我们知道了那个数字,我们就必须将它提高到10的幂次方。例如,假设输入为“357”,代码所做的是:
('7' - '0' = 7) * 10 ^ 0 =   7 +
('5' - '0' = 5) * 10 ^ 1 =  50 +
('3' - '0' = 3) * 10 ^ 2 = 300 = 
---------------------------------
                           357

1
如何在汇编中实现这个? - xsari3x
@xsari3x:只需要将代码翻译成汇编语言即可;最困难的部分是 pow() 函数,你必须自己编写它。如果你想要十六进制数字,可以使用简单的左移操作实现。 - BlackBear
1
这个算法不容易转换成汇编语言。res = res * 10 + (digit - '0') 更高效且易于实现。请参考 NASM Assembly convert input to integer? 中的 x86 汇编代码实现。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接