Lab 14 - Special Numbers

Part 1 - Using scanf

We have seen how to read input from stdin. However, if we wanted to read a number, such as an integer, it would be nice to not have to convert it from text to an integer ourselves. We will use the "scanf" function from the C library to do this for us.

Scanf uses a format specifier, much like printf. We will keep this simple, and use "%d" as the specifier, meaning an integer value. The code below can be used as a starting point.


        extern  printf          ; the C function, to be called
        extern  puts            ; the C function, to be called
        extern  scanf           ; the C function, to be called

        section .data           ; Data section, initialized variables
format_str:   db "%d", 0          ; The scanf format, '0'
prompt:       db "Enter an integer number: ", 0
num:          dd 0
confirm_str:  db "You entered %d as the number.", 10, 0

        section .text           ; Code section.

        global main             ; the standard gcc entry point
main:                           ; the program label for the entry point

    ; Print the prompt
    mov rdi, prompt     ; First argument for printf (address of msg)
    xor rax, rax        ; Clear rax because printf is a variadic function
    call printf         ; Use printf instead of puts: no newline

    ; Call scanf
    mov rsi, num        ; Address of num for scanf
    mov rdi, format_str ; Format string for scanf
    xor rax, rax        ; Clear rax because scanf is a variadic function
    call scanf

    ; Now that we have the number,
    ; print it back out to the user.
    mov rdi, confirm_str  ; Format string
    mov esi, [num]        ; Load the value num to print 
    mov rax, 0
    call printf

    ret
Call this "scanf_example.asm", assemble it, link it, and run it. Test it out 3 times (with 3 different numbers) to verify that it works as expected. We will use this again below.




Part 2 - Squaring a number

Copy the code from part 1 to "lab14_pt2.asm" and update the comments accordingly. Keep the part that prompts the user for a number and uses scanf to read it. Load the number into a register, and multiply it with itself, then store the result in memory. Create a new string to print "square of the number is " followed by a number (i.e. "%d"). Use this string to print the result you obtained.

Test it out 3 times (with 3 different numbers) to verify that it works as expected.




Part 3 - Cubing a number

Copy the code from part 2 to "lab14_pt3.asm" and update the comments accordingly. Keep the part that prompts the user for a number and uses scanf to read it. Load the number into a register, and multiply it with itself. Next, multiply it by itself again, then store the result in memory. Create a new string to print "cube of the number is " followed by a number (i.e. "%d"). Use this string to print the result you obtained.

Test it out 3 times (with 3 different numbers) to verify that it works as expected.

Questions:


Part 4 - Checking if a number is a Narcissistic Number or not, for a given int

A Narcissistic Number, is also called an Armstrong number. The idea is this: an n-digit number is a Narcissistic Number if the sum of the digits raised to the nth power is equal to the number.

For example, 371 = 3^3+7^3+1^3, so it is a Narcissistic Number.
Another example: 1634 = 1^4+6^4+3^4+4^4, so it is a Narcissistic Number.
(These two examples are from the wolfram.com website).

The goal for this part is to determine if a 3-digit number is a Narcissistic Number or not.

The code below will be helpful in finding if an input number is a Narcissistic Number or not.

div_loop:
    xor rdx, rdx                      ; Clear rdx each time before division
    mov rbx, 10                       ; Set divisor to 10
    div rbx                           ; Divide rax by 10, quotient in rax, remainder in rdx

    ; Cube the remainder
    mov rcx, rdx                      ; Move remainder to rcx for cubing
    imul rcx, rcx                     ; Square rcx
    imul rcx, rdx                     ; Cube rcx (remainder)

    add rsi, rcx                      ; Add cube of remainder to rsi

    ; Check if there are more digits to process
    test rax, rax                     ; Test quotient for zero
    jnz div_loop                      ; If quotient not zero, loop
For the input number, print a message that it is a Narcissistic Number or not.

Also, check to make sure that the number has only 3 digits. If the user does not enter a 3 digit number, print an error message and exit.

Test this out for the following numbers: 137, 153, 167, 222, 371, and 407. Verify that the results are correct.

Questions:


In this lab, we have learned: