【问题标题】:Multi-Digit Input from NASM来自 NASM 的多位输入
【发布时间】:2012-12-04 05:59:22
【问题描述】:

所以我是汇编语言的新手,我对基础知识有相当扎实的掌握,但用户输入总是让我感到困惑。所以现在我有以下代码来接收用户的单个数字:

mov eax, 3
mov ebx, 0
mov ecx, inStrBuf
mov edx, StrLen
int 80h

然后定义如下

SECTION .bss
inStrBuf:  times StrLen resb  ' ' 

Section .data
StrLen: equ 8 

我把值放入ecx后,就是数字+2608。所以我一直在做的只是简单地减去2608得到数字。现在,当我输入多个数字时,例如数字 46,当我转换为十进制时,我得到 669236。没有像以前那样仅减去 2608 的简单方法。

首先,2608 是怎么回事,有没有办法只接受像 654 这样的数字并将其放入寄存器(当然是十六进制值)。谢谢!

【问题讨论】:

    标签: assembly nasm


    【解决方案1】:

    我不知道2608是从哪里来的,更不用说669236了!总体思路是:

    ;zero out someplace to put result
    top:
    ;get a digit/character
    ;make sure it represents a decimal digit
    ;(if not - go to done)
    ;subtract '0' to convert character to number
    ;multiply "result so far" by 10
    ;add in the new number
    ;go to top
    done:
    

    这是我平时用的...

    section .bss
        inStrBuf resb StrLen ; 12+ is good...
    
    section .text
        ...
        push inStrBuf ; pass parameter on stack
        call atoi
        add esp, 4 ; clean up stack
        mov [someplace], eax
        ...
    
    ;--------------------
    atoi:
        push ebx
    
        mov edx, [esp + 8]  ; pointer to string
        xor ebx, ebx ; assume not negative
    
        cmp byte [edx], '-'
        jnz .notneg
        inc ebx ; indicate negative
        inc edx ; move past the '-'
    .notneg:
    
        xor eax, eax        ; clear "result"
    .top:
        movzx ecx, byte [edx]
        inc edx
        cmp ecx, byte '0'
        jb .done
        cmp ecx, byte '9'
        ja .done
    
        ; we have a valid character - multiply
        ; result-so-far by 10, subtract '0'
        ; from the character to convert it to
        ; a number, and add it to result.
    
        lea eax, [eax + eax * 4]
        lea eax, [eax * 2 + ecx - '0']
    
        jmp short .top
    .done:
        test ebx, ebx
        jz .notminus
        neg eax
    .notminus:
        pop ebx
        ret
    ;------------------------
    

    这使用两个leas 的“聪明”方法乘以十,减去'0',并添加新的数字。它的缺点是不设置标志,所以我们不能检查溢出——它只是默默地翻转。任何“无效”字符停止 - 适用于 xero、换行(sys_read 将在那里)...或“垃圾”。当它返回时,“无效”字符将在 ecx 中(只是 cl 很有趣),并且 edx 指向下一个字符。方便解析“192.168.1.1”左右。您可能更喜欢使用更直接的东西。 :) C 库“atoi”或“scanf”工作......如果你想那样做......

    真的很好奇那个 2608 是从哪里来的!

    【讨论】:

    • 您可以使用sub ecx, '0' / cmp ecx, 9 / ja .done,因此您可以省略 LEA 的 -'0' 组件(这会将其在 Intel CPU 上的延迟从 1 个周期降低到 3 个周期)。即,您的循环将在此更改后以大约两倍的速度运行,并删除一个条件分支。
    猜你喜欢
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    • 2019-02-03
    • 2015-09-08
    • 2021-04-20
    • 1970-01-01
    • 2017-03-04
    • 2012-09-10
    相关资源
    最近更新 更多