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 28 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).