0

I'm trying to take in a byte of information, really number and compare them. My comparisons are generating the wrong input. Here's the code.

program dateDemo;
#include ("stdlib.hhf")

static
    dayR: byte;
    monthR: byte;
    yearR: word;

    day: uns8;
    month: uns8;
    year: uns16;

    packedDate: dword;

begin dateDemo;


    stdout.put( "Enter the current month, day, and year: " );
    stdin.get( monthR, dayR, yearR );

    mov( 0, eax );
    mov(0, bx);
    mov( eax, packedDate ); // Just in case there is an error.

    mov(monthR, ah);
    mov(ah, month);
    mov(dayR, al);
    mov(al, day);
    mov(yearR, bx);
    mov(bx, year);

    // Pack the data into the following bits:
    //
    // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
    // m m m m d d d d d y y y y y y y

    if( month > 12 ) then
        stdout.put( "Month value is too large", nl );

    elseif( month = 0 ) then
        stdout.put( "Month value must be in the range 1..12", nl );

    elseif( day > 31 ) then
        stdout.put( "Day value is too large", nl );

    elseif( day = 0 ) then
        stdout.put( "Day value must be in the range 1..31", nl );

    elseif( year > 99 ) then
        stdout.put( "Year value must be in the range 0..99", nl );

    else    
        stdout.put("It worked");

        /*mov( month, al );
        shl( 5, ax );
        or( day, al );
        shl( 7, ax );
        or( year, al );
        mov( ax, packedDate );*/

    endif;

I left out some code that doesn't matter. If I enter, "10 20 1997" it outputs, "Month is too large" I tried to do the comparison with an uns8 instead of hte byte information but to no avail. Can anyone give me tips.

Also my year will go up to 2000 so it will use a whole 16-bit word.

MaxAttax
  • 67
  • 6
  • If you're just going to copy them literally, what's the point of having separate `month` and `monthR`? `byte` and `uns8` are the same size. How does `stdin.get` know to parse strings into numbers? Does it really word-split on space and parse into the right types? Or are you maybe just getting the ASCII bytes? **Use a debugger to check what values you're getting.** – Peter Cordes Sep 24 '18 at 04:07
  • If the types are byte and word, stdin.get will treat the input as hexadecimal (= `stdin.geth8` and `stdin.geth16`). Input "10" will be stored as 0x10 = 16d, which is greater than 12. Change the types to uns8 and uns16. – rkhb Sep 24 '18 at 12:34

1 Answers1

1

ENVIRONMENT

  • HLA (High Level Assembler - HLABE back end, POLINK linker) Version 2.16 build 4413 (prototype)
  • Windows 10

NOTE

  • The code in this question is copied from the dateDemo example in chapter 2 section 11, Bit Fields and Packed Data, in Randall Hyde's The Art of Assembly Language.

SOLUTION

  • The demoDate example packs and unpacks a word date representation, therefore the example should be altered to use a dword long packed date format if you want to use a word for your year value.
  • Long packed date format:
|31 . . . . . . . . . . . . . . 16|15 . . . . . . 8|7 . . . . . . 0|
| y y y y y y y y y y y y y y y y | m m m m m m m m|d d d d d d d d|

EXAMPLE

  • The code below is the demoDate example altered to handle the dword long packed date format.
program LongDateDemo;
#include ("stdlib.hhf")

storage
    Day:            uns8;
    Month:          uns8;
    Year:           uns16;
    LongPackedDate: dword;

begin LongDateDemo;
    stdout.put("Enter the current month, day, and year (EX: 6 14 2020): ");
    stdin.get(Month, Day, Year);

    // Long packed date format
    // |31 - 16|15 - 8|7 - 0| 
    // |year   |month |day  |

    mov(0, EAX);
    mov(EAX, LongPackedDate ); // Just in case there is an error.

    if( Month > 12 ) then
        stdout.put( "Month value is too large", nl );

    elseif( Month = 0 ) then
        stdout.put( "Month value must be in the range 1..12", nl );

    elseif( Day > 31 ) then
        stdout.put( "Day value is too large", nl );

    elseif( Day = 0 ) then
        stdout.put( "Day value must be in the range 1..31", nl );

    elseif( Year > 65535 ) then
        stdout.put( "Year value must be in the range 0..65535", nl );

    else    
        mov(Year, AX);
        shl(8, EAX);
        or(Month, AL);
        shl(8, EAX);
        or(Day, AL);
        mov(EAX, LongPackedDate);
    endif;

    // Okay, display the packed value:

    stdout.put("Packed data = $", LongPackedDate, nl);

    // Unpack the date:

    mov(LongPackedDate, EAX);
    and($FF, AL);   // Retrieve the day value.
    mov(AL, Day);

    mov(LongPackedDate, EAX);
    shr(8, EAX);
    and($FF, AL);   // Retrieve the month value.
    mov(AL, Month);

    mov(LongPackedDate, EAX);
    shr(16, EAX);
    and($FFFF, AX); // Retrieve the year value.
    mov(AX, Year);

    stdout.put("The date is: ", Month, "/", Day, "/", Year, nl);

end LongDateDemo;
Kuma
  • 427
  • 5
  • 17