1

I was multiplying every integer of a buffer and now I need to connect the intermediate results.

I have this code: (previously in .data I stated: count db 0)

MOV cx, ax
MOV si, offset skBuf
MOV di, offset raBuf
add si,ax
dec si

work:
MOV dl, [si]

sub dl,48
mov bl,dl
mov al,3        ;can be changed by 0-9
mul bl
mov dl,al
add dl,48

divide: 
cmp dl,09H     ;compares with 9
jbe pabaiga    
ja decomposition

decomposition:

mov ax,dx

mov bl, 10
div bl         ;al=ax/bl  ah=ax%bl 

MOV [di], ah
mov dl,al
add dl,count
mov count,al
add count,48

dec si
inc di
LOOP    work

I feel like I'm doing something wrong.

Basically if you didn't understand:
For example my buffer contains: 456
Right now without the divide part of a code it multiplies each digit by 3 so:

  • 6*3 and prints it
  • then 5*3 and prints it
  • and lastly 4*3 and prints it all separately

I need that the output looked like 456*3 which equals to 1368


Right now with this code below:

    MOV cx, ax
    MOV si, offset skBuf
    MOV di, offset raBuf
    add si,ax
    dec si
    
 work:
    MOV dl, [si]
    
    sub dl,48
    mov bl,dl
    mov al,3        ;galima pakeisti
    mul bl
    mov dl,al
    add dl,48
    
    MOV [di], dl
    
    dec si
    inc di
    LOOP    work

the output (with 456 input) is B?< but I need it to be 1368

If it would make it more understandable I'm reading from a file and writing it to another file.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
lulzo
  • 11
  • 3
  • 1
    Try to determine what "connecting the answer" means from a mathematical point of view. – Erik Eidt Dec 06 '22 at 21:41
  • It's not mathematical :D I tried to explain how it works now and how it needs to work below the code. I'll edit now a little bit so maybe you'll understand it better – lulzo Dec 06 '22 at 21:45
  • I don't think it's going to be magic... If not magic you can perhaps explain using logic & math. – Erik Eidt Dec 06 '22 at 21:48
  • So you *don't* want to handle each ASCII digit separately? Sounds like you want [NASM Assembly convert input to integer?](https://stackoverflow.com/q/19309749) or a DOS equivalent, multiply that by 3 (e.g. `mov dx, ax` / `add ax,ax` / `add ax, dx`) then convert that back to an ASCII base10 string ([Assembly, printing ascii number](https://stackoverflow.com/a/15621644) / [Displaying numbers with DOS](https://stackoverflow.com/q/45904075)) – Peter Cordes Dec 06 '22 at 21:55
  • Okay I'll try. As I've stated right now it multiplies the each digit from a buffer's end by 3: so 6*3=18 (5*3=15, 4*3=12) I need to divide 18 by 10 (18/10=1, 18%10=8) and print mod (18%10=8) in the next buffer, then I need to store the 18/10=1 somewhere so the loop will start again 5*3=15 and when I divide 15%10=5 I need to add the last 18/10=1 to this 5 and print it out and the 15/10=1 should be stored again somewhere and repeat it with another digit of the buffer till the start of the buffer – lulzo Dec 06 '22 at 21:57
  • @SepRoland I've tried that but it didn't work out to me:(, maybe you have any codes that I could use to combine the integers? – lulzo Dec 06 '22 at 22:04
  • 1
    @SepRoland Do you know of a canonical Q&A for 16-bit `atoi`? There are a few, but almost all of them use 8-bit operand-size for `mul`, so can only handle small numbers. (like [this](https://stackoverflow.com/q/64630595) or [this](https://stackoverflow.com/questions/55840972/convert-string-to-decimal-in-assembly-language). And [How to convert a string to number in assembly language 8086?](https://stackoverflow.com/q/27703166) doesn't have a loop around what could be a loop body, and is over-complicated. Or [this](https://stackoverflow.com/q/29977483) which uses two multiplies in the loop. – Peter Cordes Dec 06 '22 at 22:25
  • I guess not since you answered this instead of closing it as a duplicate. – Peter Cordes Dec 06 '22 at 22:26
  • @PeterCordes The answer to https://stackoverflow.com/questions/72407637/inputting-multi-radix-multi-digit-signed-numbers-with-dos contains a code (*snippet 1a*) that does precisely that conversion. Of course being burried in a much larger Q/A means it won't be found that easily. I might try writing a suitable Q/A although I have my doubts writing a self-answer about something that simple... – Sep Roland Dec 06 '22 at 22:41
  • @SepRoland: Since you've already answered this question, it could be the canonical if it had a title that would let people find it. – Peter Cordes Dec 06 '22 at 22:46

1 Answers1

1

For example my buffer contains: 456
I need that the output looked like 456*3 which equals to 1368

In contrast to your current approach that starts at the end of the source string, combining the digits into a 16-bit integer ready for multiplication, is best done beginning at the start of the sequence of digits:

    mov  cx, ax
    mov  si, offset skBuf
    mov  di, offset raBuf
    xor  ax, ax
    xor  bx, bx
  work:
    mov  dx, 10
    mul  dx          ; AX = 0 then AX = 40 then AX = 450
    mov  bl, [si]
    inc  si
    sub  bl, 48
    add  ax, bx      ; AX = 4 then AX = 45 then AX = 456
    loop work

    mov  dx, 3
    mul  dx          ; AX = 1368

Then use one of the code snippets from Displaying numbers with DOS that you can freely modify to have it store into your destination buffer.

They expect me to do the same calculation to almost any sized number:/ that's why I posted asking to do the exact thing you mentioned by doing it by hand i guess. Do you have any ideas how to work with that? It's pretty much what I asked in the beginning but maybe my question was incorrectly worded

Then you need the long multiplication with a single-digit multiplier. This time it's easiest to begin at the end of the digit sequence and also store the result from the end of the destination buffer, which should have room for 1 extra character!

  mov  bx, ax      ; Length source
  lea  si, skBuf[bx - 1]
  lea  di, raBuf[bx]
  xor  cl, cl      ; Clear our carry
work:
  mov  al, [si]    ; Read character
  dec  si
  sub  al, 48      ; AL is [0,9]
  mov  ah, 3
  mul  ah          ; (digit * 3) -> AX is [0,27]
  add  al, cl
  aam              ; (digit * 3) % 10 -> AL is [0,9]
                   ; (digit * 3) / 10 -> AH is [0,2]
  add  al, 48
  mov  [di], al    ; Write character
  dec  di
  mov  cl, ah      ; (digit * 3) / 10 -> CL is carry [0,2]
  dec  bx
  jnz  work
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • I really appreciate your help! THANK YOU A LOT! But there is a problem when I'm trying to display the number, because the input (456) is too small for what my teacher is asking, and when I try to do the same code for a number that is like 1234567890123456 it doesn't work. But maybe I just don't understand how to modify it, or maybe it would be too big of a number to work with – lulzo Dec 06 '22 at 22:48
  • @lulzo: That's a huge number, needing more than 3 words (48 bits) to hold it. Maybe they're expecting you to work in BCD, similar to how you would by hand on paper with base10 digits, so you can handle arbitrary precision? Multiplying an n-digit number by a single-digit number is not too bad, you can do it in one pass if you take care of the place-values, although you'll still need some manual carry-propagation I think. – Peter Cordes Dec 06 '22 at 22:54
  • They expect me to do the same calculation to almost any sized number:/ that's why I posted asking to do the exact thing you mentioned by doing it by hand i guess. Do you have any ideas how to work with that? It's pretty much what I asked in the beginning but maybe my question was incorrectly worded – lulzo Dec 06 '22 at 22:58
  • @lulzo I've added a solution that can deal with any size numbers. – Sep Roland Dec 06 '22 at 23:36
  • @lulzo Nice to see that you're happy. Consider clicking the 'accept' checkmark on the left side. – Sep Roland Dec 06 '22 at 23:56