Search code examples
assemblyriscvrars-simulator

RISC-V Assembly Language Program to Convert Fahrenheit to Celsius


An assembly language program to convert a temperature value given in Fahrenheit to Celsius. The formula to be implemented is 𝐶 = (𝐹 − 32) × 5⁄9. Data Segments Required:

  1. F_temp (word)
  2. C_temp (word)
  3. The value 32 (byte)
  4. The value 5 (byte)
  5. The value 9 (byte)
  6. Prompt for input (string)
  7. Message for output (string)

The stack is to be used for passing the Fahrenheit value to the subroutine and for returning the calculated Celsius value back to the main program. Dynamic stack allocation is to be implemented for this. Both the Fahrenheit and the calculated Celsius values are to be stored in the allocated memory locations defined in the data segment.

What I have so far is this code. When I run the program it says

Assemble: operation completed successfully.

It is supposed to ask the user to enter a Fahrenheit temperature. But it not doing that. Also, after the user enters a number, it should convert it to Celsius and display the result.

    
    .data
F_temp:     .word   0
C_temp:     .word   0
Number1:    .byte   32
number2:    .byte   5
number3:    .byte   9
enterNumber:    .ascii "\nEnter a temperature in Fahrenheit: \n"
celsiusDegree:  .ascii "\nCelsius temperature is: "
array:      .word 0:25
welcome1:   .ascii " \n This program converts Fahrenheit to Celsius \n\n"

    .text
main:
    la a0, welcome1     #display welcome message
    li x0, 4
    ecall

    la x10,enterNumber             #Ask user to write a number
    li x17,4                  
    ecall                           

    la x6,array                   #store numbers array 
    li x30,25                     #maximum of 25 integers are allowed to be entered 

    # F is in x10               #(F-32) * 5 / 9
    addi x1, x0, 9      #t1 = 9
    addi x2, x2, 5      #t0 = 5
    addi s0, s0, 32     #s0 = 32
    sub x10, x6, s0     #F-32
    mul x10, x6, s0
    div t0, t1, s0
    
done:   
    la x10,celsiusDegree        #display celcius degree
    ecall 


exit:   

    ori a7, zero, 10    # define program exit system call
    ecall           # exit program

Solution

  • x0 is hard-wired to 0. It never makes sense to li into it. https://en.wikichip.org/wiki/risc-v/registers.

    Whatever register the ecall handler looks in for a system-call number, it's not x0. Check the documentation for whatever you're using. (e.g. RARS system-calls use a7, the same way that MARS used the MIPS register $v0 (not MIPS $0, the zero register))


    Also generally a bad idea to mix x1 and t0 / s0 register names. Easy to accidentally use 2 different names for the same register and have your code overwrite its own data.


    In a previous version of the question you had:

    Note: RISC-V multiply and divide instructions do not support immediates (constants). Therefore, all numeric values are to be defined in and loaded from memory

    That's weird, the "therefore" doesn't really follow.

    li reg, constant is still cheaper than lw, especially for a small integer. But if your assignment said you had to do it the stupid way, with data memory instead of foo = 5 or .equ assemble-time symbolic constants, then you have to. You can define your constants in one place, but then still use them as immediates, if your assembler doesn't suck.