Question
Need help with Assembly language please Modify the lab from the Fahrenheit to Celsius lab to only perform a conversion if the Fahrenheit value is
Need help with Assembly language please
Modify the lab from the Fahrenheit to Celsius lab to only perform a conversion if the Fahrenheit value is above 0x20 C-style pseudocode to describe what needs to be done is given below:
if(Fahrenheit < 0x20) { print("ERROR: The Fahrenheit temperature is less than 0x20"); // print error message exit0; // exit the program }
Essentially the program should exit if the value that was input is less than 0x20. This program modification requires the following:
Create the error message in the .data segment
convert the pseudocode to assembly using the following hints:
compare the 1-byte Fahrenheit variable value to 0x20
use a conditional jump and jump if greater to the section of the program that does the Fahrenheit to Celsius conversion
if the conditional jump is not taken:
use print_string function to print the ERROR message
use the exit0 macro to exit the program
Here is a compilation option which will run the program twice, first with a valid input and next with an input that should cause the error message to be printed:
nasm -f elf *.asm; ld -m elf_i386 -s -o lab3 *.o; lab3 0x40; lab3 0x19
When the compilation option shown above is used, the following output should be produced:
Farhenheit Temperature:0x40
Celsius Temperature: = 0x11
Farhenheit Temperature:0x19
The Fahrenheit temperature is less than 0x20
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; Fahrenheit to Celcsius with valid input check;;;;;;;;;;;;;;;;;
; recieves an 8-bit HEX Fahrenheit Temperature through command line parameter
; outputs the Celsius approximation (in HEX) to the std_out
;
;
; Compiler option: nasm -f elf *.asm; ld -m elf_i386 -s -o lab3 *.o; lab3 0x40
;
; example output when input is valid:
; Fahrenheit Temperature: 0x40
; Celsius Temperature: 0x11
;
;
; example output when input is too low:
;
; Fahrenheit Temperature: 0x1F
;
; ERROR: The Fahrenheit temperature is less than 0x20
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;; CONSTANT DEFINITIONS ;;;;;;;;;;;;;;;;;;;;
null equ 0x00
MAXARGS equ 1
sys_exit equ 1
sys_read equ 3
sys_write equ 4
stdin equ 0
stdout equ 1
stderr equ 3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;; MACRO DEFINITIONS ;;;;;;;;;;;;;;;;;;;;;;;;
; print_char macro
; prints one ascii character to the console
%macro print_char 1
mov eax, 4 ;system call number (sys_write)
mov ebx, stdout ;file descriptor (stdout)
mov ecx, %1 ;address of data to print
mov edx, 1 ;number of bytes to print
int 0x80 ;do it!
%endmacro
; exit0 macro
; exits program with return code 0
%macro exit0 0
mov ebx, 0
mov eax, sys_exit
int 0x80
%endmacro
;;;;;;;;;;;;;;;;;;;; END MACRO DEFINITIONS ;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; DATA SEGMENT ;;;;;;;;;;;;;;;;;;;;;;;;
SECTION .data
hexprefix db "0x",null
debugOK db "OK",null
nl db 0x0a,0x0d
fmsg db "Farhenheit Temperature:",null
cmsg db "Celsius Temperature: = ",null
Fahrenheit db 0xff ; 0xff is default value
Celsius db 0xff ; 0xff is default value
;;;;; error messages ;;;;;
szErrMsg db "Too many arguments. The max number of args is !", null
szLineFeed db 10
szBErrMsg db "Invalid number of hex digits entered.",null
properMsg db "Proper 2 digit hex value: 0x4F",null
arg1nullMsg: db "First argument is null",null
arg2nullMsg: db "Second argument is null",null
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;; BSS SEGMENT ;;;;;;;;;;;;;;;;;;;;
section .bss
tmpbyte resb 1 ;hold byte temporarily for the hex to ascii conversion
tmphexchar resb 2 ;holds hex version of ascii char to be printed
arg1hex resb 1 ;holds the hex value of first argument
arg2hex resb 1 ;holds the hex value of second argument
arg1ascii resb 5 ;holds the ascii version of first argument (4 characters and a null)
arg2ascii resb 5 ;holds the ascii version of second argument (4 characters and a null)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;; TEXT SEGMENT ;;;;;;;;;;;;;;;;;;;;
SECTION .text
global _start
_start: ;;;;; BEGIN MAIN PROGRAM SECTION ;;;;;
nop
;;;;;;;;;;;;;;;;;;;; Get arguments from the stack ;;;;;;;;;;;;;;;;;;;;
push ebp ; save ebp on stack
mov ebp, esp ; set base pointer to stack pointer
cmp dword [ebp + 4], 1 ; check to see if no args were received (arg count will always be at least 1)
je NoArgs ; if no args entered (arge count == 1) then go to program exit section
cmp dword [ebp + 4], MAXARGS+1 ; check if total args entered is more than the maximum
ja TooManyArgs ; if total is greater than MAXARGS, show error message and exit
mov ebx, 3 ; ebx is index into the argument pointer array
; since ebp was pushed, args pointer array starts @ [ebp+12] = [ebp +4*3] = [ebp+4*ebx]
;;;;; Get first command line argument! ;;;;;
mov edi, dword [ebp + 4 * ebx] ; put pointer address of an arg into edi
test edi, edi ; test to see if pointer address is null (i.e. check if edi equal to 0)
jz arg1Null ; exit loop if edi == 0 (argument 1 is a null string)
call GetStrlen ; string length will be returned in edx register
mov ecx, dword [ebp + 4 * ebx] ; put address of first argument into ecx register
; EXIT program if invalid length hex value detected in first arg
cmp edx, 4 ; check for length of string to be 4 (not including null character)
jne invalidHexByte ; if the lengh is incorrect then go to show error and exit
; put first arg string into arg1ascii and then print to std_out
mov al, [ecx]
mov [arg1ascii], al ; put first character into arg1ascii
mov al, [ecx + 1]
mov [arg1ascii + 1], al ; put second character into arg1ascii
mov al, [ecx + 2]
mov [arg1ascii + 2], al ; put third character into arg1ascii
mov al, [ecx + 3]
mov [arg1ascii + 3], al ; put fourth character into arg1ascii
mov byte [arg1ascii + 4], null ; put null character at end of arg1ascii
mov edi, fmsg
call print_string
mov edi, arg1ascii ;output argument 1 in ascii
call print_string
call print_nl
;convert arg1ascii to raw data
mov eax, [arg1ascii] ; four ascii digits is the 32-bits that will go into eax to be converted
call ascii_hex_byte_to_raw ; convert the ascii hex quantity to raw data
mov [Fahrenheit], al
;;;;;;;;;;;;;;;;;;;;; DO NOT MODIFY ANYTHING ABOVE THIS COMMENT!
;;;;;;;;;;;;;;;;;;;;; perform celsius = 5 * (Fahrenheit-32) / 9
; check to see if the fahrenheit value is above 0x20
; if(Fahrenheit < 0x20)
; {
; print("The Fahrenheit temperature is less than 0x20");
; exit0
; }
;
Fahrenheit_greater_than_0x20:
;compute the Celsius value
mov al, [Fahrenheit] ; al = Fahrenheit value
sub al, 32 ; al = Fahrenheit - 32
mov dl, 5 ; prepare for multiplication
mul dl ; ax = 5 * (Fahrenheit-32)
mov dl, 9 ; prepare for division
div dl ; al = 5 * (Fahrenheit-32) / 9
mov [Celsius], al ;put sum of variable values into the "sum" variabel
;print Celsius message and the Celsius value
mov edi, cmsg ;put address of celsius message in edi register
call print_string ;print celsius message
mov edi, Celsius ;put address of Celsius variable in edi register
call print_hex_byte ;print Celsius HEX value
call print_nl ;print newline
;;;;;;;;;;;;;;;;;;;; DO NOT MODIFY ANYTHING BELOW THIS COMMENT!
exit0 ;Exit program to Operating System
NoArgs:
; No args entered,
; start program without args here
jmp arg1Null
TooManyArgs:
mov edi, szErrMsg
call print_string
call print_nl
exit0
invalidHexByte:
mov edi, szBErrMsg
call print_string
call print_nl
mov edi, properMsg
call print_string
call print_nl
exit0
arg1Null:
mov edi, arg1nullMsg
call print_string
call print_nl
exit0
arg2Null:
mov edi, arg2nullMsg
call print_string
call print_nl
exit0
;;;;; end of main function
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;; FUNCTIONS/SUBROUTINES ;;;;;;;;;;;;;;;;;;;;
;;print newline
; returns - nothing
print_nl:
mov eax, 4 ;system call number (sys_write) - p75 of Assembly Language Tutorial
mov ebx, 1 ;file descriptor (stdout)
mov ecx, nl ;address of data to print
mov edx, 2 ;number of bytes to print
int 0x80 ;do it!
ret
;;print hexadecimal prefix characters "0x"
; uses - eax, ebx, ecx, edx
; returns - nothing
print_0x:
mov eax, 4 ;system call number (sys_write) - p75 of Assembly Language Tutorial
mov ebx, 1 ;file descriptor (stdout)
mov ecx, hexprefix ;address of data to print
mov edx, 2 ;number of bytes to print
int 0x80 ;do it!
ret
;print_string
; recieves - address of a C-Style String in register edi
; C-Style means null terminated
; uses - eax, ebx, ecx, edx
; returns - nothing
print_string:
mov ecx, edi
checknull:
cmp byte [ecx],null
jz endstring
print_char ecx
inc ecx
jmp checknull
endstring:
ret
;print byte of data
; recieves - address of a data byte in register edi
; uses - eax, ebx, ecx, edx, tmpbyte, tmphexchar
; returns - nothing
print_hex_byte:
call print_0x ;print hex prefix
mov al, [edi] ;get hex byte to be printed
mov [tmpbyte], al ;put hex byte into tempbyte variable
and byte [tmpbyte], 0x0f ;isolate lower hex digit in bl
shr al, 4 ;isolate upper hex digit in al
;
mov ah, al ;pass upper hex digit to hex_char_to_ascii
call hex_char_to_ascii ;convert upper hex digit to ascii
mov [tmphexchar], ah
print_char tmphexchar
;
mov ah, [tmpbyte] ;pass lower hex digit to hex_char_to_ascii
call hex_char_to_ascii ;convert lower hex digit to ascii
mov [tmphexchar], ah
print_char tmphexchar
;
ret
;convert one hex character to ascii
; recieves - hex value in register ah
; uses - ah register
; returns - ascii encoded hex char in ah register
hex_char_to_ascii:
cmp ah, 10
jl hexlessthan10 ;check if hex digit is a through f
add ah, 0x07 ;adjust value for hex digit a through f
hexlessthan10:
add ah, 0x30 ;add ascii encoding
ret
;convert one hex byte in ascii to a raw data byte
; recieves - ascii encoded hex value with 0x prefix in register ax
; uses - ah register
; returns - raw data hex value in al register
ascii_hex_byte_to_raw:
ror eax, 16
cmp al, '9' ; see if hex character is '9' or less
jle lowCharLT9 ;
sub al, 7 ; offset the ascii value if it is A-F
lowCharLT9:
and al, 0x0f ; remove ascii encoding
cmp ah, '9' ; see if hex character is '9' or less
jle highCharLT9 ;
sub ah, 7 ; offset the ascii value if it is A-F
highCharLT9:
and ah, 0x0f ; remove ascii encoding
shl al, 4
add al, ah
ret
;get length of a C-Style string from command line argument passed in stack
;taken from http://www.dreamincode.net/forums/topic/285550-nasm-linux-getting-command-line-parameters/
; recieves - address of string in edi register
; uses - eax, ecx registers
; returns - address of the string into edx register
GetStrlen:
push ebx ;put ebx register data on the stack
xor ecx, ecx ;clear ecx register
not ecx ;set ecx = 0xffffffff, ecx will be decremented by repne as non-null characters are counted
xor eax, eax ;clear eax register, al will be used by scasb to search for null character
cld ;clear direction flag, index registers are incremented
repne scasb ;search for 0 in string; if not found edi++, ecx--, and check next character
;scasb: compares AL and [ES:EDI], EDI +=1 pcasm page 109
;repne: repeat instruction while string char not null (string char != AL) pcasm page 110
mov byte [edi - 1], 10 ;append newline character in place of null?
not ecx ;1's complement ecx, it will now contain address of an arg
pop ebx ;restore ebx value from stack
lea edx, [ecx - 1] ;put address of the string into edx register??
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EOF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started