Search This Blog

Sunday, February 19, 2023

MARS MIPS - A Program to echo output from the Keyboard


Introduction

The aim to write a program that demonstrates the use of peripheral devices like keyboard. The program should echo what is being getting typed in the keyboard. The post describes the code that generates the output shown in the video.

This is me practicing basic stuff to be done in the MIPS assembly language program.


Code Section

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Module 10 Memory Mapped I/O Demo

# Memory mapped address of device registers.

# 0xFFFF0000 rcv contrl

# 0xFFFF0004 rcv data

# 0xFFFF0008 tx contrl

# 0xFFFF000c tx data        
.data

.eqv    MMIOBASE    0xffff0000

# Receiver Control Register (Ready Bit)
.eqv    RCR_        0x0000
.eqv    RCR         RCR_($s0)

# Receiver Data Register (Key Pressed - ASCII)
.eqv    RDR_        0x0004
.eqv    RDR         RDR_($s0)

# Transmitter Control Register (Ready Bit)
.eqv    TCR_        0x0008
.eqv    TCR         TCR_($s0)

# Transmitter Data Register (Key Displayed- ASCII)
.eqv    TDR_        0x000c
.eqv    TDR         TDR_($s0)
.text
.globl  main

main:
    li      $s0,MMIOBASE            # get base address of MMIO area

keyWait:
    lw      $t0,RCR                 # get control reg
    andi    $t0,$t0,1               # isolate ready bit
    beq     $t0,$zero,keyWait       # is key available? if no, loop

    lbu     $a0,RDR                 # get key value

displayWait:
    lw      $t1,TCR                 # get control reg
    andi    $t1,$t1,1               # isolate ready bit
    beq     $t1,$zero,displayWait   # is display ready? if no, loop

    sb      $a0,TDR                 # send key to display

    li      $v0,11
    syscall

    j       keyWait

Here's a high-level overview of what the code is doing:

  1. It defines memory-mapped addresses for four registers: Receiver Control Register (RCR), Receiver Data Register (RDR), Transmitter Control Register (TCR), and Transmitter Data Register (TDR).

  2. In the main function, it initializes a register $s0 with the MMIO base address.

  3. It enters a loop that waits for a keypress by checking the value of the ready bit in the RCR register. Once a keypress is detected, the code retrieves the ASCII code of the key from the RDR register.

  4. The code then enters another loop that waits for the display to be ready to receive data by checking the value of the ready bit in the TCR register. Once the display is ready, the code sends the ASCII code of the key to the display by storing it in the TDR register.

  5. Finally, the code calls the syscall function to display the key on the screen and then jumps back to the beginning of the loop to wait for the next keypress.


Conclusion

This assembly language program that demonstrates Memory-Mapped I/O (MMIO). MMIO is a method of communication between the CPU and peripheral devices where memory locations are used to represent the device's control and data registers.

Tuesday, February 14, 2023

MARS MIPS - A Program to move a block of object


Introduction


This program draws a series of adjacent rectangles of different colors and positions on a 512x256 pixel display with a base address of 0x10010000 in memory. The program starts by defining two colors, 'color' (red) and 'black' and a block of memory 'frameBuffer' to hold the pixel data for the display. Then, a series of adjacent rectangles is drawn by calling the 'rectangle' function for each one, each time with different left x-coordinate (xmin), top y-coordinate (ymin), width and height values. The 'rectangle' function sets the color for each rectangle, checks that the rectangle is within the display bounds, and then uses a nested loop to draw the rectangle pixel by pixel by storing the color value for each pixel in the 'frameBuffer' memory block. The main program then makes a syscall to display the pixel data.

Code Section

In the .data section of the code, we define the frameBuffer to hold the pixel data for the display, as well as the colors we'll be using. Then, in the .text section, we define the rectangle function which sets the color for each rectangle and draws it pixel by pixel using a nested loop.
Next, we show an example of how to draw a rectangle with a specific position and size using the rectangle function. We then repeat this process multiple times to draw a series of adjacent rectangles in different positions and colors.


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Important: do not put any other data before the frameBuffer
# Also: the Bitmap Display tool must be connected to MARS and set to
#   display width in pixels: 512
#   display height in pixels: 256
#   base address for display: 0x10010000 (static data)

.data
frameBuffer:	.space 0x80000
color:		.word 0x00ff0000
black:		.word 0x00000000

.text

# Example of drawing a rectangle; left x-coordinate is 100, width is 25
# top y-coordinate is 200, height is 50. Coordinate system starts with
# (0,0) at the display's upper left corner and increases to the right
# and down.  (Notice that the y direction is the opposite of math tradition.)

			li $a0,200	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			#lw $t0, color
			lw $t0,color
			jal rectangle
			li $v0,32
			li $a0,500
			syscall
			lw $t0, black
			li $a0,200	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			jal rectangle
			li $a0,210	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			lw $t0, color
			jal rectangle
			li $v0,32
			li $a0,500
			syscall 
			lw $t0, black
			li $a0,210	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			jal rectangle
			li $a0,220	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			lw $t0, color
			jal rectangle
			li $v0,32
			li $a0,500
			syscall 
			lw $t0, black
			li $a0,220	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			jal rectangle
			li $a0,230	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			lw $t0, color
			jal rectangle
			li $v0,32
			li $a0,500
			syscall
			lw $t0, black
			li $a0,230	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			jal rectangle
			li $a0,240	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			lw $t0, color
			jal rectangle
			li $v0,32
			li $a0,500
			syscall
			lw $t0, black
			li $a0,240	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			jal rectangle
			li $a0,250	# left x coordinate  
			li $a1,50		# width
			li $a2,100	# top y coordinate (y increases downward)
			li $a3,25		# height
			lw $t0, color
			jal rectangle
			li $v0,10
			syscall
rectangle:

# $a0 is xmin (i.e., left edge; must be within the display)
# $a1 is width (must be nonnegative and within the display)
# $a2 is ymin  (i.e., top edge, increasing down; must be within the display)
# $a3 is height (must be nonnegative and within the display)
			beq $a1,$zero,rectangleReturn # zero width: draw nothing
			beq $a3,$zero,rectangleReturn # zero height: draw nothing

			#li $t0,-1 # color: white
			#lw $t0, color
			la $t1,frameBuffer
			add $a1,$a1,$a0         		# simplify loop tests by switching to first too-far value
			add $a3,$a3,$a2
			sll $a0,$a0,2                 # scale x values to bytes (4 bytes per pixel)
			sll $a1,$a1,2
			sll $a2,$a2,11               	# scale y values to bytes (512*4 bytes per display row)
			sll $a3,$a3,11
			addu $t2,$a2,$t1         	# translate y values to display row starting addresses
			addu $a3,$a3,$t1
			addu $a2,$t2,$a0         	# translate y values to rectangle row starting addresses
			addu $a3,$a3,$a0
			addu $t2,$t2,$a1         	# and compute the ending address for first rectangle row
			li $t4,0x800                 	# bytes per display row
rectangleYloop:
			move $t3,$a2 # pointer to current pixel for X loop; start at left edge
rectangleXloop:
			sw $t0,($t3)
			addiu $t3,$t3,4
			bne $t3,$t2,rectangleXloop       # keep going if not past the right edge of the rectangle
			addu $a2,$a2,$t4                 # advace one row worth for the left edge
			addu $t2,$t2,$t4                 # and right edge pointers
			bne $a2,$a3,rectangleYloop       # keep going if not off the bottom of the rectangle
			
rectangleReturn:
			jr $ra

Conclusion

Using MIPS assembly language programming, we can draw a series of adjacent rectangles with different colors and positions on a 512x256 pixel display. This program can be used to move a block of objects on the display, making it a useful tool for game development or other applications.