如何将用户输入整数保存到寄存器

时间:2015-03-19 03:59:57

标签: assembly x86 nasm

我不确定如何将用户输入数据实际存储到寄存器中。我想提示用户输入一个带符号的base-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

特别突出我做错了什么?

2 个答案:

答案 0 :(得分:2)

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

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

.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 <之后) / strong>)你将它乘以-1。对于这两种情况,你最好创建另一个string2number并将其命名为string2numberSigned,它是相同的,但它会将循环停在1而不是零(以避免将“ - ”转换为数字)。

希望这会对你有所帮助。

答案 1 :(得分:1)

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

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

处添加值

jmp endwhile将无条件地跳到最后,所以你应该使用je endwhile,只有当值相等时才会跳转。 另外,在尝试将al的结果累积到bx之前,你应该这样做,因为其他方面你会在你的数字中包含回车符。最后请记住所有读入的数字很可能是ASCII ,所以角色&#39; 0&#39;将是48岁,&#39; 1&#39;将是49等,所以在将它们用作整数之前你必须减去48。

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

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