assemblyx86hexhla

Dollar Value Menu Assembly Program (HLA)


I'm having trouble finding where my errors are in the program I've written. I need this to be printed out when I enter 1240:

Feed me 4 hex digits: 1240
1 $1 item
1 $2 item
1 $3 item
0 $4 item
0 $5 item
Total Order Costs: $6

This is what I get when executed:

Feed me your order as 4 hex digits: 1240
0 $1 item
3 $2 item
3 $3 item
2 $4 item
0 $5 item
Total Order Costs: $0

Also I have no idea how to make my program take this 76C9 as an input and it has to print out:

Feed me 4 hex digits: 76C9
7 $1 item
3 $2 item
3 $3 item
1 $4 item
1 $5 item
Total Order Costs: $31

When I tried to run it, I get a conversion error which I understand. It's because the program only takes integers which is why it leads to an error, but I really have no idea how to make the program take the input.

This is my current code:

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

static
    orderValue: int16;  

begin DollarValueMenu;
    stdout.put("Feed me your order as 4 hex digits: ");
    stdin.get(orderValue);  

    mov(orderValue, ax);  

    // Initialize dx as the total cost accumulator
    mov(0, dx);

    // Extracting $1 items
    mov(ax, cx);
    and(7, cx);  
    stdout.puti16(cx);  
    stdout.put(" $1 item");
    stdout.newln();

    // Compute cost for $1 items by adding cx 
    add(dx, cx);  

    // Extracting $2 items
    mov(ax, cx);
    shr(3, cx);  
    and(7, cx);  
    stdout.puti16(cx);  
    stdout.put(" $2 item");
    stdout.newln();

    // Compute cost for $2 items
    mov(bx, cx);  
    add(bx, bx);  
    add(dx, bx); 

    // Extracting $3 items
    mov(ax, cx);
    shr(6, cx);  
    and(7, cx);  
    stdout.puti16(cx);  
    stdout.put(" $3 item");
    stdout.newln();

    // Compute cost for $3 items
    mov(bx, cx);  
    add(bx, bx);  
    add(bx, cx);  
    add(dx, bx);  

    // Extracting $4 items
    mov(ax, cx);
    shr(9, cx);  
    and(7, cx);  
    stdout.puti16(cx);  
    stdout.put(" $4 item");
    stdout.newln();

    // Compute cost for $4 items
    shl(2, cx);  
    add(dx, cx);  // Add cost of $4 items to total

    // Extracting $5 items
    mov(ax, cx);
    shr(12, cx);  
    and(7, cx);  
    stdout.puti16(cx);  
    stdout.put(" $5 item");
    stdout.newln();

    // Compute cost for $5 items
    mov(bx, cx);  // Move count to bx
    shl(2, bx);  
    add(bx, cx);  
    add(dx, bx);  // Add cost of $5 items to total

    // Output the total cost
    stdout.put("Total Order Costs: $");
    stdout.puti16(dx);  // Output total cost
    stdout.newln();

end DollarValueMenu;

This is what I get when executed:

Feed me your order as 4 hex digits: 1240
0 $1 item
3 $2 item
3 $3 item
2 $4 item
0 $5 item
Total Order Costs: $0


Solution

  • stdout.put("Feed me your order as 4 hex digits: ");
    stdin.get(orderValue);
    mov(orderValue, ax);
    

    I'm not a regular user of the High Level Assembler, but I seem to remember that "HLA reads in hexadecimal format when you read directly into a register".

    stdout.put("Feed me your order as 4 hex digits: ");
    stdin.get( ax );
    

    And it could be a good idea to prefix your input with a $ character so as to denote that it is indeed hexadecimal that follows.


    Feed me 4 hex digits: 1240 1 $1 item 1 $2 item 1 $3 item 0 $4 item 0 $5 item Total Order Costs: $6
    Feed me 4 hex digits: 76C9 7 $1 item 3 $2 item 3 $3 item 1 $4 item 1 $5 item Total Order Costs: $31

    From these examples it becomes clear what is expected. Sadly, your current program contains 2 fundamental errors:

    The order of operands

    Consider this snippet:

    mov(bx, cx);  // Move count to bx
    shl(2, bx);  
    add(bx, cx);  
    add(dx, bx);  // Add cost of $5 items to total
    

    In HLA, the source is the leftmost operand and the destination is the rightmost operand. You can easily remember this by looking at an instruction like shl(2, bx) where it is simply impossible for the leftmost operand (an immediate number) to be the destination of anything. That has got to be the source operand then.

    mov(cx, bx);  // Move count to bx
    shl(2, bx);  
    add(cx, bx);  
    add(bx, dx);  // Add cost of $5 items to total in DX
    

    The order of items (in this task)

    Consider the hexadecimal numbers $1240 and $76C9:

    $1240 == %0001'0010'0100'0000 == %0'001'001'001'000'000
    $76C9 == %0111'0110'1100'1001 == %0'111'011'011'001'001
                                         ^   ^   ^   ^   ^
                                         |   |   |   |   + $5 items
                                         |   |   |   + $4 items
                                         |   |   + $3 items
                                         |   + $2 items
                                         + $1 items
    

    The code should look more like this:

    stdin.get( ax );
    
    // Extracting $1 items
    shl(1, ax);                // drop the 16th bit (unused)
    rol(3, ax);                // brings the triplet of interest into the lowest bits
    mov(ax, cx);
    and(7, cx); 
    stdout.puti16(cx);  
    stdout.put(" $1 item");
    stdout.newln();
    
    // Add cost for $1 items by moving CX to DX
    mov(cx, dx);
    
    // Extracting $2 items
    rol(3, ax);                // brings the triplet of interest into the lowest bits
    mov(ax, cx);
    and(7, cx); 
    stdout.puti16(cx);  
    stdout.put(" $2 item");
    stdout.newln();
    
    // Add cost for $2 items
    add(cx, dx);
    add(cx, dx);
    
    // Extracting $3 items
    rol(3, ax);                // brings the triplet of interest into the lowest bits
    mov(ax, cx);
    and(7, cx); 
    stdout.puti16(cx);  
    stdout.put(" $3 item");
    stdout.newln();
    
    // Add cost for $3 items
    add(cx, dx);
    add(cx, dx);
    add(cx, dx);
    

    Should be easy enough to continue from here...