0

I am unsure of how to actually store user-input data to a register. I would like to prompt the user for a signed base-10 integer, then store that integer to the bx register. What I have does not seem to be actually storing any data from what I can tell:

;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

Anything in particular sticking out that I'm doing wrong?

Jud
  • 1,324
  • 3
  • 24
  • 47

2 Answers2

2

To store user-input data to a register, you have to capture the data as a string of characteres, then create your own procedure to convert from string to number, and finally store the result in BX register.

Next program captures an unsigned number with maximum 4 digits, convert it to number and store it in BX, it's plenty of comments to help you understand, and it was made with EMU8086 compiler (just copy, paste and run) :

.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    

If you change BX and want to display it later, you will have to create your own procedure to convert from number to string (the algorithm is easier than string2number).

To make it work with signed numbers, just check if the first character of the string is "-" (minus), in such case, convert the number without that character and, after the conversion (after string2number) you multiply it by -1. For both cases, you better create another string2number and name it string2numberSigned, it's the same, but it stops the loop at 1, not at zero (to avoid convert "-" into a digit).

Hope this helps you.

1

The way you've structured your code, you want to be using the 01 interrupt, which reads and returns a single character, instead of the 0A, which reads the line into a buffer you give it.

mov bx, ax will override the value in bx, so if you have 119, only the 9 would get stored. instead you should be multiply bx by 10 and then adding the value at al.

jmp endwhile will unconditionally jump to the endwhile, so instead you should be using je endwhile which will only jump if the values are equal. Additionally you should be doing this before you try and accumulate the result of al to bx, as other wise you'll include the carriage return in you number read in. Finally keep in mind all number read in will most likely be in ASCII, so the character '0' will be 48, '1' will be 49, etc. so you will have to subract 48 before using them as integers.

mov dx, [bx] will load the data at the address to which ds:bx points to, which in this case is meaningless. Instead you have to have a region of memory allocated, convert your number back to a string, and then give the address of that region. This is roughly as much work as it was to read in the number.

Overall a significant amount of rewriting will need to be done in order to do what you want. Unless this is for learning purposes I would stick with the standard c libraries methods for i/o and using 64 bit x86 instead of 16 bit.

vandale
  • 3,600
  • 3
  • 22
  • 39