Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

daa and das

ASMcatASMcat Member Posts: 10
Can somebody explain these instructions to me? When and why are they used? Thanks!

Comments

  • DariusDarius Member Posts: 1,666
    : Can somebody explain these instructions to me? When and why are they used? Thanks!
    :

    No offense, but for the most part they aren't. They are used for BCD (Binary Coded Decimal) arithmetic, but as noone really uses that anymore, those opcodes aren't used often. Nowadays they are sometimes used for little tricks.

    "We can't do nothing and think someone else will make it right."
    -Kyoto Now, Bad Religion

  • ASMcatASMcat Member Posts: 10
    Okay, in this code:

    > hex2asc:
    > push ax ; save al = 0xa9
    > shr al,1
    > shr al,1
    > shr al,1
    > shr al,1 ; high nibble --> low nibble, al = 0x0a
    > add al,0x90
    > daa
    > adc al,0x40
    > daa ; al = ascii = 0x41 (="A")
    > mov bx,[buffpt]
    > mov [bx],al
    > inc bx
    > mov [buffpt],bx
    > pop ax ; restore al = 0xa9
    > and al,0x0f ; mask high nibble, al = 0x09
    > add al,0x90
    > daa
    > adc al,0x40
    > daa ; al = ascii = 0x39 (="9")
    > mov bx,[buffpt]
    > mov [bx],al
    > inc bx
    > mov [buffpt],bx
    > ret

    What do those four DAA instructions do?
  • DariusDarius Member Posts: 1,666
    : Okay, in this code:
    :
    : > hex2asc:
    : > push ax ; save al = 0xa9
    : > shr al,1
    : > shr al,1
    : > shr al,1
    : > shr al,1 ; high nibble --> low nibble, al = 0x0a
    : > add al,0x90
    : > daa
    : > adc al,0x40
    : > daa ; al = ascii = 0x41 (="A")
    : > mov bx,[buffpt]
    : > mov [bx],al
    : > inc bx
    : > mov [buffpt],bx
    : > pop ax ; restore al = 0xa9
    : > and al,0x0f ; mask high nibble, al = 0x09
    : > add al,0x90
    : > daa
    : > adc al,0x40
    : > daa ; al = ascii = 0x39 (="9")
    : > mov bx,[buffpt]
    : > mov [bx],al
    : > inc bx
    : > mov [buffpt],bx
    : > ret
    :
    : What do those four DAA instructions do?
    :

    First off here's the algorithm that DAA performs
    [code]
    if ( (AL and 0Fh) > 9 or (AuxC = 1)) then
    al := al + 6
    AuxC := 1 ;Set Auxilliary carry.
    endif
    if ( (al > 9Fh) or (Carry = 1)) then
    al := al + 60h
    Carry := 1; ;Set carry flag.
    endif
    [/code]

    You would perform this after adding two packed BCD numbers together in binary (ie with add). Packed BCD numbers use 4 bits to represent one decimal digit. The high nibble represents the 10's place and the low nibble represents the 1's place and the greatest value that a byte can hold in BCD is 99 represented as 0x99. Here's a simple example that should make it fairly clear what DAA does.

    Suppose you add 1 and 9. The result would be 0xA. If you were to then perform daa you would get

    0xA > 0x9 therefore al=al+6 (0xA + 6 = 0x10).
    So it just converts the hex value into a BCD number by adding 6 (10 + 6 = 16 = 0x10) if the low nibble is above 9, and it does the same for the high nibble. A place where BCD may be useful is embedded programming where you are controlling the logic for those 8 section LED lights (like digital clocks). But otherwise you'll probably NEVER use it.

    In this case it's being used as a trick to convert values less than 9 to ASCII values '0'-'9' (0x30-0x39) and values greater than 9 to ASCII values 'A'-'F' (0x41-0x46). This only works because they are exactly 0x11 apart (if they were 0x10 apart changing the adc to add would also work, but if they were 0x12 apart then it wouldn't work at all).

    The way it works is it adds 130 BCD to the value (the value being either the low or high nibble isolated). Since BCD can only be in the range of 0-99 (in a byte) it will wrap. So, if the values are between 0-9 the daa's do nothing and you get, for example, 130+9=139 and taking off the carry you get 0x39 which is '9'. The carry flag isn't set at the adc if the values are between 0 and 9 (because you have 0x90 + 9 = 0x99 which isn't overflow). Now, if 'A' was 0x40 instead of 0x41 and two multiples of 10 (or maybe any two BCD numbers that added up to 130 BCD) would work. However, as 'A' is 0x41 you need a way to add in that extra one. Adc will add in that extra one if the carry is set, so you need a way to set the carry if the value is greater than 0x9. The way the algorithm does that is by using 0x90 as the first number. As the comments are illustrating 0x90+0xA is the same as 90 BCD + 10 BCD and as you see that's 100 BCD which is 0x100 and doesn't fit, ie it overflowed and set the carry flag. Now adc will add the necessary 1 as it's adding the 0x40 (the other half of the 130 BCD). If it wasn't for that one then the following algorithm would work.

    mov al, anibble add al, 0x30
    daa
    would be value between BCD 30-45. 0-9 would be 30-39 and A-F would be 40-45. Alas, we need that one so we use 130 to set the carry flag.

    As you can see, this is one of those tricks I was talking about as this isn't what daa was meant for. However there is a hidden form of aam and aad that can be useful.

    "We can't do nothing and think someone else will make it right."
    -Kyoto Now, Bad Religion

  • Chris BrownChris Brown USAMember Posts: 4,496 ✭✭

    __ { http://forcoder.org } free ebooks and video tutorials about [ C, Scratch, C++, PL/SQL, Visual Basic, Go, JavaScript, Visual Basic .NET, Delphi, Python, R, Java, PHP, C#, Assembly, Swift, MATLAB, Perl, Objective-C, Ruby Transact-SQL, Lisp, SAS, VBScript, Crystal, ABAP, Rust, Lua, Clojure, F#, Dart, Hack, Alice, FoxPro, Scheme, Kotlin, D, LabVIEW, Erlang, Logo, Apex, COBOL, Prolog, Scala, Fortran, ML, Ada, Awk, Bash, Julia ] ___________

Sign In or Register to comment.