简体   繁体   中英

How can i multiply 2 number together and form 4 digit and then display it?

So the program start like this:

.data
num db 22
multiplier db 20
divide db 10
digit1 db ?
digit2 db ?
digit3 db ?
digit4 db ?
.code
MOV AL,num
MUL multiplier
;----22 x 20 = 440
MOV BH,AH
;----AH stores 04?? AL stores 40?
;----40
DIV divide
MOV digit1,AH
MOV digit2,AL
;----04
MOV AL,BH
DIV divide
MOV digit3,AH
MOV digit4,AL

;---display
MOV AH,02H
MOV DL,digit1
INT 21H
;---same for digit2,3,4

What the program print out is bunch of hex number. Can someone tell me how to store the 3 digit number or 4 digit number. Is it store in AX or still AL?

Why do you think ah may be 04 and al 40?

I ask for two reasons.

1) if you would debug it, the debugger should be able to show you current value of ah , al . Although it probably shows hexa form of ax , and you don't understand hexa numbers, so that may be like one more thing for you to learn.

2) you are missing then the point of "bits". al is 8 bit of information, that means it can contain 2 8 different pieces of information. As each bit can be 0 or 1 (two options), and you have 8 bits, positioned - order matters. If you would check combinatorics theory, that's "two raised to eighth power" of all possible combinations, and that's 256. Now those combinations are most often used as binary numbers, when treated as numbers from 0 to 255 (check the binary form to see how the bit patterns are assigned to particular numbers, it's logical, each bit representing one of the powers of two, just as in our decimal format each digit is representing particular power of ten).

All gibberish talk you may think, show me the bug. With your logic the number 100 would be split between ah:al as 01:00. So maximum number in al would be 99. That's wasting another 3/5 of possible combinations (up to 255).

The 440 is in binary (bits) encoded as: 0000 0001 1011 1000 , first 8 bits are in ah , that equals to 1 , other 8 bits are in al , those equals to (440 - ah*256) = (440 - 1*256) = 184. (the value 256 in ax is split as 1 : 0 in ah : al , 255 is split as 0 : 255 ). If you put values h : l into ah : al , the ax has value 256*h + l .

In debugger you would probably read: ax 01B8 . The hexadecimal format has this neat feature, that each digit is exactly 4 bits long. 0 = 0000 , 1 = 0001 , B (11 in decimal) = 1011 , 8 = 1000 . So the first two digits are content of ah , other two digits are content of al .

Read some more about bits, bytes, and do some math exercises to fully grasp how the conversion between binary <-> decimal <-> octal <-> hexadecimal works, just calculate it by hand few times. Especially doing some basic dec <-> bin/hex math from head is very handy when programming in ASM, for example when you treat content of register as bit mask and not number, it's usually easier to write down the hex form of the value, than to recalculating all set bits into decimals and summing them.


Back to your code now (each paragraph is either a bug description, or at least very strong code style suggestion, you should follow, in case you want me ever to take a look on your source again).

This is MASM or TASM I suppose. I don't like mov al,num , it hides the fact that you are actually getting the content of memory, not address. mov al,[num] is more exact definition of what's happening in CPU. You can write it like that even in TASM (when needed, size of data is then specified by byte ptr [...] .

div byte ptr [mem8] divides ax with value in [mem8], in your case you divide 440 by 10. That will produce 0 remainder into ah , and quotient 44 into al . The "bug" is not in the instruction itself, but in your expectations. You store ah as digit1 , but it's not font digit, it's value digit from 0 to 9. To turn it into font glyph, you need ASCII encoded digit. You have to transform it into ASCII encoding (check ASCII table to see which glyph has what code). So add ah,30h would fix digit1.

Digit2 is completely off, as you can see, 44 is not even value in 0 to 9 range, so it can't be turned into single digit, you have to repeat the whole process, but this time starting with one order of 10 lower (so set ax to 44, not 440). Then rewrite it into a loop.

MOV AL,BH DIV divide - now you divide ax by byte 10 , while you didn't set AH . It can contain anything after that digit1 adventure, luckily for you in your version AH was 0 . Either do movzx ax,bh , or xor ah,ah to zero-extend the 8 bit value of bh into 16 bit ax . (results of DIV and encoding into ASCII is explained above)

Finally you display digit1 as first, but what was digit1? Remained of division by 10 of the original value. So for 440 you will accidentally output 0 , 4 , 4 , 0 (well, will not, as content of digit1-2-3-4 is not correct), looking like 440, but in reversed order. Try 22*49 = 1078 for debugging (if your code would produce correct digit# values, it would print 8701 then).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM