0

I am trying to shift the number input by user by 1, since SHL is equivalent to the multiple of 2, this is why I am shifting the input by 2 to print the multiples of 2.

Here is my code,

MOV AH,01H
INT 21H

MOV DL,AL

MOV AH, 02H
INT 21H 

MOV CX,10

L1:
    SHL DL,1
    MOV AH, 02H
    INT 21H 
LOOP L1


MOV AX, 4CH ; RETURN TO MS-DOS
INT 21H

The service 01 of INT 21H takes a character input from the user. which in this case is a number, on each iteration the loop shift 1 to the left. Unfortunately this does not happen.

micheller
  • 183
  • 1
  • 9
  • 24
  • 1
    If the user enters a `1`, your code doesn't see a `1`, it sees an ASCII `'1'`, which is equal to `31h`. Subtract `30h` from the input to turn it into a numeric `1`, then add `30h` to each digit of the shifted result to turn it back into ASCII. – DCoder Sep 16 '12 at 13:10
  • No idea what code you're testing now, nor what specifically "doesn't work" means. – DCoder Sep 16 '12 at 13:28
  • actually i am trying to print this, 2,4,6,8,10,12,14,16,18,20 can you help me with the code ? i just need an explanation or example ccode ? – micheller Sep 16 '12 at 13:34
  • I guess you really need to be more specific for anyone to help... – IdiotFromOutOfNowhere Sep 16 '12 at 13:59
  • Sir, i just need a user to input a number and then print the multiples of those numbers on the screen. i couldn't be able to use input interrupts as i couldn't find enough help on the google – micheller Sep 16 '12 at 14:04
  • That's not multiplication by 2... that's adding 2 to the previous result. There is nothing magic about that, store the last result in one variable, in each step of the loop, update the result, copy it into another variable, [convert that variable to ASCII](http://stackoverflow.com/a/9114996/1233508), and print it. As a starting point, `mov bx, 01h; mov cx, 0Ah; L1: mov dx, bx; shl dx, 01h; /* convert dx to ascii */; /* print each byte of the result */; loop L1; mov ax, 4Ch; int 21h`. – DCoder Sep 16 '12 at 14:14

1 Answers1

1

You need to subtract '0' / 48d / 0x30 from the value of dl to get the numeric value of the character insted of ASCII value, before shifting it. Shifting ASCII values doesn't make sense for multiplication. Then add '0' to dl before printing.

mov cx,10

sub dl,'0' ; convert ASCII value to numeric value: '0' -> 0, '1' -> 1 ... 

L1:
    shl dl,1
    mov ah,02h
    add dl,'0' ; convert numeric value to ASCII value: 0 -> '0', 1 -> '1' ...
    int 21h
    sub dl,'0' ; convert ASCII value back to numeric value: '0' -> 0, '1'
loop L1
nrz
  • 10,435
  • 4
  • 39
  • 71
  • 1
    The interesting part begins once you reach `dl = 8` and `shl` produces `16`. – DCoder Sep 16 '12 at 14:17
  • @DCoder I agree. Another issue is when `dl >= 128` and `shl` causes overflow. How complicated the proper printing routine is needed here depends on the required numerical range. In 8086 up to 65535 it's easy, up to 4294967295 still quite easy, but after 4294967295 it gets complicated IMHO (in 16-bit 8086 assembly). There are answered questions on printing numbers, although most are 32-bit 386+ code, not 8086 code: http://stackoverflow.com/questions/11270118/multiplying-two-values-and-printing-them-to-the-screen-nasm-linux http://stackoverflow.com/questions/9113772/assembly-numbers-to-ascii – nrz Sep 16 '12 at 22:09