【问题标题】:How to save user-input integer to a register如何将用户输入的整数保存到寄存器
【发布时间】:2015-03-19 03:59:56
【问题描述】:

我不确定如何将用户输入的数据实际存储到寄存器中。我想提示用户输入一个带符号的以 10 为底的整数,然后将该整数存储到 bx 寄存器中。我所拥有的似乎并没有真正存储我所知道的任何数据:

;get user input

   mov   ah, 0Ah
   int   21h


while:
    mov   bx, ax        ;save char to bx
    cmp   ax, 13        ;is char = carriage return?
    jmp   endwhile      ;if so, we're done
    int   21h           ;get another char
    loop  while
endwhile:
    ret                 ;end loop

;print data stored in bx to console

    mov   ah, 09
    mov   dx, [bx]
    int   21h

有什么特别突出我做错了吗?

【问题讨论】:

  • 您必须将数字捕获为字符串,然后使用您自己的转换程序将其转换为数字。
  • 如果你显示 BX,你只会看到二进制字符。为了显示 bx 的内容,您必须将其转换为字符串。要显示 [ BX ],您必须将其指向一个字符串。

标签: assembly x86 nasm


【解决方案1】:

要将用户输入的数据存储到寄存器中,您必须将数据捕获为字符串,然后创建自己的过程将字符串转换为数字,最后将结果存储到 BX 寄存器中。

下一个程序捕获一个最多4位的无符号数,将其转换为数字并将其存储在BX中,它有很多帮助你理解的cmets,它是用EMU8086编译器制作的(只需复制,粘贴和运行):

.stack 100h
;------------------------------------------
.data
;------------------------------------------
msj1   db 'Enter a number: $'
string db 5 ;MAX NUMBER OF CHARACTERS ALLOWED (4).
       db ? ;NUMBER OF CHARACTERS ENTERED BY USER.
       db 5 dup (?) ;CHARACTERS ENTERED BY USER. 
msj2   db 13,10,'Number has been converted',13,10,13,10,'$'
;------------------------------------------
.code          
;INITIALIZE DATA SEGMENT.
  mov  ax, @data
  mov  ds, ax
;------------------------------------------        
;DISPLAY MESSAGE.
  mov  ah, 9
  mov  dx, offset msj1
  int  21h
;------------------------------------------
;CAPTURE CHARACTERS (THE NUMBER).
  mov  ah, 0Ah
  mov  dx, offset string
  int  21h
;------------------------------------------
  call string2number
;------------------------------------------        
;DISPLAY MESSAGE.
  mov  ah, 9
  mov  dx, offset msj2
  int  21h
;------------------------------------------
;STOP UNTIL USER PRESS ANY KEY.
  mov  ah,7
  int  21h
;------------------------------------------
;FINISH THE PROGRAM PROPERLY.
  mov  ax, 4c00h
  int  21h           
;------------------------------------------
;CONVERT STRING TO NUMBER IN BX.
proc string2number         
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
  mov  si, offset string + 1 ;NUMBER OF CHARACTERS ENTERED.
  mov  cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.                                         
  mov  ch, 0 ;CLEAR CH, NOW CX==CL.
  add  si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
  mov  bx, 0
  mov  bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:         
;CONVERT CHARACTER.                    
  mov  al, [ si ] ;CHARACTER TO PROCESS.
  sub  al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
  mov  ah, 0 ;CLEAR AH, NOW AX==AL.
  mul  bp ;AX*BP = DX:AX.
  add  bx,ax ;ADD RESULT TO BX. 
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
  mov  ax, bp
  mov  bp, 10
  mul  bp ;AX*10 = DX:AX.
  mov  bp, ax ;NEW MULTIPLE OF 10.  
;CHECK IF WE HAVE FINISHED.
  dec  si ;NEXT DIGIT TO PROCESS.
  loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.
  ret 
endp    

如果您更改 BX 并希望稍后显示它,则必须创建自己的过程来从数字转换为字符串(该算法比 string2number 更容易)。

要使其与有符号数字一起使用,只需检查字符串的第一个字符是否为“-”(减号),在这种情况下,转换没有该字符的数字,并在转换后(在 string2number) 你把它乘以-1。对于这两种情况,您最好创建另一个 string2number 并将其命名为 string2numberSigned,它是相同的,但它会在 1 处停止循环,而不是在零处(以避免将“-”转换为数字)。

希望对你有所帮助。

【讨论】:

    【解决方案2】:

    按照您构建代码的方式,您希望使用 01 中断,它读取并返回单个字符,而不是 0A,它将行读入您给它的缓冲区。

    mov bx, ax 将覆盖bx 中的值,因此如果您有 119,则只会存储 9。相反,您应该将 bx 乘以 10,然后将值添加到 al。

    jmp endwhile 将无条件跳转到 endwhile,因此您应该使用 je endwhile,它只会在值相等时跳转。 此外,您应该在尝试将 al 的结果累积到 bx 之前执行此操作,否则您将在读入的数字中包含回车符。最后请记住,读入的所有数字很可能都是 ASCII,所以字符“0”将是 48,“1”将是 49,依此类推,因此您必须先减去 48,然后才能将它们用作整数。

    mov dx, [bx] 会将数据加载到 ds:bx 指向的地址,在这种情况下是没有意义的。相反,您必须分配一个内存区域,将您的数字转换回字符串,然后给出该区域的地址。这与读取数字的工作量大致相同。

    总体而言,需要进行大量重写才能完成您想做的事情。除非这是出于学习目的,否则我会坚持使用标准 c 库方法进行 i/o 并使用 64 位 x86 而不是 16 位。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-26
      • 2021-09-29
      • 1970-01-01
      相关资源
      最近更新 更多