0

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?

Leong JC
  • 11
  • 1
  • 2
  • 1
    As a side note, there's like million of SO answers how to display a number in x86 assembly, some of them quite detailed almost like a tutorial. Search for them. But first learn some theory about bits/bytes, bin/dec/hex and ASCII, so you don't get lost so fast. Also have around instruction set reference guide, so you can easily verify what registers are affected by `DIV`, etc.. – Ped7g Aug 17 '16 at 12:22
  • 2
    Check for example this answer: http://stackoverflow.com/a/15621644/4271923 ... BTW, there's one special case when `440` will be stored as 4:40 in ah:al. It's called BCD number format. The x86 processor has special instructions supporting this, to make basic calculations (add/sub mainly) in BCD possible, and conversion to strings faster. Unless really curious, you can forget about it now, I'm adding it here just for completeness, that your case of 440 split to 4:40 can happen in real world too, but with completely different code and for different reasons. – Ped7g Aug 17 '16 at 12:36
  • To display a number you need a procedure = http://stackoverflow.com/questions/29568631/how-to-print-the-contents-of-a-register-in-emu8086/29568921#29568921 – Jose Manuel Abarca Rodríguez Aug 17 '16 at 15:08

1 Answers1

0

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

Ped7g
  • 16,236
  • 3
  • 26
  • 63
  • Thank you for explain this. – Leong JC Aug 17 '16 at 13:19
  • Can u make a sample program for me to display a number that is over 255 in AL? i experiencing some strange issue here. A sample program will help. The program is about 97 x 9, i need to display the result. I'm new to assembly :3 sry for not understand much of your explaination previously. – Leong JC Aug 18 '16 at 10:14
  • `AL` is 8 bit. That's 0 to 255 when treated as unsigned binary value. Or -128 to +127 when treated as signed binary value. Binary `1111 1111` means all 8 bits set to `1`, the value is (^ = power here, not xor) 2^0 + 2^1 + .. + 2^7 = 255. To define number over 255 you need more than 8 bits (or apply some lossy conversion, like AL*2 for only even numbers = effective range 0 to 510, missing the 2^0 info bit). `AH` is also 8 bits wide. `AH` `AL` combined together form the `AX`, which is 16b, that's 0 to 65535 or -32768 to 32767 (may be written as `AH:AL`, where the colon is like visual separator). – Ped7g Aug 18 '16 at 10:34
  • @LeongJC so I'm not sure what example can I provide to you. Can you show what piece of code is giving you strange issues? I can then try to explain the "strange" part. Also try few more times to read trough the answer, and point out particular things you get lost at, maybe one by one. But look firstly at binary<->dec<->hex conversion, how to calculate it, and how binary numbers are written (just get some math lecture or something, google). Then figure out that one digit in binary formatting is exactly one physical bit inside CPU. Then things should make lot more sense (AL/AX/EAX limits, etc). – Ped7g Aug 18 '16 at 10:41
  • 97*9 = 873, in binary 0011 0110 1001 = 10 bits at least required, you can't store that number into `AL` then. When you do `mov al,97` `mov ah,9` `mul ah`, the result of `al`*`ah` is stored into `ax` (overwriting both `al` and `ah`, as those are parts of `ax`) This is not "logical" behaviour of `MUL`, this stems from Intel definition of the instruction and x86 architecture. So whenever you are not sure, check instruction set reference guide, some details with some instructions can be very tricky to recall from memory. On x86 the MUL/DIV is giving lot of headaches to new programmers. :) – Ped7g Aug 18 '16 at 10:56
  • MOV AL,data1 MUL data2 ;-- after the multiply, the AX should store 0369H and in decimal is 873. ;-- the problem is how to display it out? the question is about a retail system. ;-- data1 is the item price ;-- data2 is the quantity ;-- actually the data1 is 97.50 which have the decimals places. But i ignore it. ;-- well my school lecturer only show us how to display 2 digit. ;-- for 3 digit, i can only display the number below 255 – Leong JC Aug 18 '16 at 11:33
  • @LeongJC See my comment under OP with link to example source. BTW, if you did some bin<->dec conversions calculations, you should now understand why humans write 255 as "255" (split into groups of 10^i), so you just have to write algorithm for that. With your current level of knowledge don't even think about doing real "retail" code, that's done completely differently (if the school is like "and in similar way you can do the retail code", then change the school .. I have seen recently too many people willing to calculate prices with floating point ... to have mercy with such bullshit). – Ped7g Aug 18 '16 at 11:49
  • (BTW, I'm not saying you should give up, I'm just saying you have to push hard and get few levels up. In math, in theory, algorithms ... actually it looks like you got quite far with assembly itself, after you will be able to connect all the dots, you may do quite well, it just takes time and experimenting a lot - to realize how all of that connects together) – Ped7g Aug 18 '16 at 11:57
  • Erm, i using dosbox :x... not emulator. – Leong JC Aug 18 '16 at 15:38
  • @LeongJC I have no idea how that is important here and why you added it (= I don't understand you, sorry. If you have problem, try to describe it again). Anyway, dosbox *is* emulator of DOS-like PC AT machine. It is very nice tool and a good way to run asm experiments (isolated from real OS - this helps a lot in case you code some disaster by accident), usually also easier to debug: either with some SW debugger like TD.EXE, or you can get special dosbox debug build with integrated debugger (check dosbox forums). – Ped7g Aug 18 '16 at 16:02