Assembly Language Tutorial 4

Raspberry Pi LogoIn this part of my Assembly Language Tutorial I will cover how to convert decimal values into floats, storing and loading floats, performing arithmetic on floats, comparing floats and how to implement a Switch statement in assembly language. If you haven’t seen my previous tutorials please watch those first or you may be very confused.

All of the code along with a transcript of the video follows below the video.

If you like videos like this, consider throwing a dollar at me on Patreon.

[googleplusone]

Code & Transcript

XXVIII. Floating Point Numbers

	1. The use of floating point numbers is provided by the Vector Floating Point (VFP) coprocessor. The VFP provides single precision (32 bit) and double precision (64 bit) for floating point numbers. 
	
	2. Floats start with a positive (0) or negative (1) bit that represents the sign.
	
	3. Bits 30 through 23 represent the exponent 
	
	4. (SLIDE) Bits 22 through 0 represent the fraction. This is referred to as the Mantissa. Just like we can have 0.40625 we can calculate the IEEE format binary
	
		a. .40625 * 2 = 0.8125 (0)
		b. .8125 * 2 = 1.625 (1)
		c. .625 * 2 = 1.25 (1)
		d. .25 * 2 = 0.5 (0)
		e. .5 * 2 = 1 (1)
		f. So .40625 == .01101
		g. Normalize 0.01101 = 1.101 (-2)
		h. Exponent is 127 - 2 = 125 (01111101)
		i. It is positive so the first bit it 0
		j. .40625 = 0 01111101 10100000000000000000000 B
	
	5. (SLIDE) We can't store floats in R0 - R15 so the VFP provides registers S0 - S31 for single precision and D0 - D15 for double precision. Each Dn is mapped to 2 Sn registers
	
	6. @ Print Pi
	@ Used by the compiler to tell libc where main is located
	.global main
	.func main
	
	main:
		LDR R1, addr_pi @ Get the address associated with Pi
		
		@ There are 32 Sx registers for storing floats
		@ Store the value of R1 in a word
		VLDR S0, [R1] @ Move Pi value into S0
		
		@ VCVT is used to convert between floats and integers
		@ This converts to B64 because printf requires a 
		@ double precision value
		@ F64 - Convert to Binary 64
		@ F32 - From Binary 32
		@ D5 - Store in double precision register
		@ S14 - From the current single precision register
		VCVT.F64.F32 D1, S0
		
		LDR R0, =output @ Point to the string
		
		@ Insert the floating point value in R2 and R3 to hold
		@ the double precision value
		VMOV R2, R3, D1
		
		@ When printf is called for a float it looks for the value
		@ in registers R2 and R3
		BL printf @ Print the string
		
	end:
		MOV R7, #1
		SWI 0
		
	addr_pi:
		.word pi
		
	.data
	pi: .float 3.141592
	output: .asciz "The value of Pi is %f\n"
	
	@ Define we want to use printf
	.global printf
	
	7. When performing arithmetic 2 modes are used.
	
		a. Scalar : Used when the destination is in S0 - S7 or D0 - D3. 
		
		b. Vector : The operation operates with registers wrapping from the first to others in the bank
		
	8. Adding floats
	.global main
	.func main
	
	main:
		@ Store float in S0
		LDR R1, addr_num_1
		VLDR S0, [R1]
		
		@ Store float in S1
		LDR R2, addr_num_2
		VLDR S1, [R2]
		
		@ Add floats use f32 for single and f64 for double precision
		@ Also VSUB, VMUL, VDIV, VABS, VSQRT
		VADD.f32 S2, S0, S1
		
		@ Convert for double precision for printf
		VCVT.F64.F32 D1, S2
		
		@ Set the output
		LDR R0, =output
		
		@ Move into proper registers for printf
		VMOV R2, R3, D1
		
		BL printf

	end:
		MOV R7, #1
		SWI 0
		
	addr_num_1: .word num_1
	addr_num_2: .word num_2
		
	.data
		num_1: .float 1.2345
		num_2: .float 1.1111
		output: .asciz "1.2345 + 1.1111 = %f\n"
	
	.global printf
		
	9. The VFP has its own version of CPSR, called the FPSCR, that provides the flags N, Z, C and V. We can use them for conditional execution.
	
	10. Demonstrate comparing floats
	.global main
	.func main
	main:
		LDR R1, addr_num_1
		VLDR S0, [R1]
		
		LDR R2, addr_num_2
		VLDR S1, [R2]
		
		@ Compare values and set flags
		VCMP.F32 S0, S1
		
		@ Copy flags to the ARM status register 
		VMRS APSR_nzcv, FPSCR
		
		@ Conditionally assign a value
		@ Also you can check LT, GT, LE, GE
		MOVEQ R1, #1
		MOVNE R1, #0
		
		@ Set the output
		LDR R0, =output
		
		BL printf
		
	end:
		MOV R7, #1
		SWI 0
		
		addr_num_1: .word num_1
		addr_num_2: .word num_2
		
	.data
	num_1: float 1.234
	num_2: float 5.678
	output: .asciz "Are numbers equal : %d\n"
	
	.global printf
	
XXIX. Switch

	1. Implement a switch statement in assembler
	.global main
	.func main
	main:
		MOV R2, #1
		
		CMP R2, #0
		BEQ case_0
		
		CMP R2, #1
		BEQ case_1
		
		B case_def
		
	case_0:
		LDR R0, =output_0
		B end
		
	case_1:
		LDR R0, =output_1
		b end
		
	case_def:
		LDR R0, =output_def
	
	end:
		BL puts
		MOV R7, #1
		SWI 0
		
	.data
	output_0: .asciz "It's 0"
	output_1: .asciz "It's 1"
	output_def: .asciz "I don't know what it is"
		
	.global puts

Leave a Reply

Your email address will not be published. Required fields are marked *