Converting MIPS assembly to C - c

I am working on converting MIPS to C, and I've been stuck on this for several days.
I've started with manually converting MIPS to C, and even though I've been working on it for several days, my resulting program in C still doesn't run as needed, and I feel like there is a small mistake that I overlooked, and I would really appreciate your help.
I started conversion with toplevel_fnc, and then with subroutine_fnc.
Here is a part of the MIPS code.
Subroutine:
build/program-mips: file format elf32-tradbigmips
Disassembly of section my_text:
00404ed0 <subroutine_fnc>:
404ed0: 27bdffd8 addiu sp,sp,-40
404ed4: afbe0024 sw s8,36(sp)
404ed8: 03a0f025 move s8,sp
404edc: afc40028 sw a0,40(s8)
404ee0: 8fc40028 lw a0,40(s8)
404ee4: 27c20018 addiu v0,s8,24
404ee8: 00402825 move a1,v0
404eec: 24060001 li a2,1
404ef0: 24020fa3 li v0,4003
404ef4: 0000000c syscall
404ef8: afc70008 sw a3,8(s8)
404efc: afc2000c sw v0,12(s8)
404f00: 8fc20008 lw v0,8(s8)
404f04: 00000000 nop
404f08: 14400004 bnez v0,404f1c <subroutine_fnc+0x4c>
404f0c: 00000000 nop
404f10: 8fc2000c lw v0,12(s8)
404f14: 10000002 b 404f20 <subroutine_fnc+0x50>
404f18: 00000000 nop
404f1c: 2402ffff li v0,-1
404f20: afc20010 sw v0,16(s8)
404f24: 8fc20010 lw v0,16(s8)
404f28: 00000000 nop
404f2c: 04410006 bgez v0,404f48 <subroutine_fnc+0x78>
404f30: 00000000 nop
404f34: 24040001 li a0,1
404f38: 24020fa1 li v0,4001
404f3c: 0000000c syscall
404f40: afc70008 sw a3,8(s8)
404f44: afc20014 sw v0,20(s8)
404f48: 8fc20010 lw v0,16(s8)
404f4c: 00000000 nop
404f50: 14400004 bnez v0,404f64 <subroutine_fnc+0x94>
404f54: 00000000 nop
404f58: 00001025 move v0,zero
404f5c: 10000002 b 404f68 <subroutine_fnc+0x98>
404f60: 00000000 nop
404f64: 83c20018 lb v0,24(s8)
404f68: 03c0e825 move sp,s8
404f6c: 8fbe0024 lw s8,36(sp)
404f70: 27bd0028 addiu sp,sp,40
404f74: 03e00008 jr ra
404f78: 00000000 nop
and toplevel:
00404f7c <toplevel_fnc>:
404f7c: 27bdffc0 addiu sp,sp,-64
404f80: afbf003c sw ra,60(sp)
404f84: afbe0038 sw s8,56(sp)
404f88: 03a0f025 move s8,sp
404f8c: afc00018 sw zero,24(s8)
404f90: 10000040 b 405094 <toplevel_fnc+0x118>
404f94: 00000000 nop
404f98: 83c30034 lb v1,52(s8)
404f9c: 2402005c li v0,92
404fa0: 14620022 bne v1,v0,40502c <toplevel_fnc+0xb0>
404fa4: 00000000 nop
404fa8: 8fc20018 lw v0,24(s8)
404fac: 00000000 nop
404fb0: 24420001 addiu v0,v0,1
404fb4: afc20018 sw v0,24(s8)
404fb8: 24040001 li a0,1
404fbc: 3c020041 lui v0,0x41
404fc0: 244260e0 addiu v0,v0,24800
404fc4: 00402825 move a1,v0
404fc8: 24060002 li a2,2
404fcc: 24020fa4 li v0,4004
404fd0: 0000000c syscall
404fd4: afc7001c sw a3,28(s8)
404fd8: afc20020 sw v0,32(s8)
404fdc: 8fc2001c lw v0,28(s8)
404fe0: 00000000 nop
404fe4: 14400004 bnez v0,404ff8 <toplevel_fnc+0x7c>
404fe8: 00000000 nop
404fec: 8fc20020 lw v0,32(s8)
404ff0: 10000002 b 404ffc <toplevel_fnc+0x80>
404ff4: 00000000 nop
404ff8: 2402ffff li v0,-1
404ffc: afc20024 sw v0,36(s8)
405000: 8fc20024 lw v0,36(s8)
405004: 00000000 nop
405008: 04410022 bgez v0,405094 <toplevel_fnc+0x118>
40500c: 00000000 nop
405010: 24040001 li a0,1
405014: 24020fa1 li v0,4001
405018: 0000000c syscall
40501c: afc7001c sw a3,28(s8)
405020: afc20028 sw v0,40(s8)
405024: 1000001b b 405094 <toplevel_fnc+0x118>
405028: 00000000 nop
40502c: 24040001 li a0,1
405030: 27c20034 addiu v0,s8,52
405034: 00402825 move a1,v0
405038: 24060001 li a2,1
40503c: 24020fa4 li v0,4004
405040: 0000000c syscall
405044: afc7001c sw a3,28(s8)
405048: afc2002c sw v0,44(s8)
40504c: 8fc2001c lw v0,28(s8)
405050: 00000000 nop
405054: 14400004 bnez v0,405068 <toplevel_fnc+0xec>
405058: 00000000 nop
40505c: 8fc2002c lw v0,44(s8)
405060: 10000002 b 40506c <toplevel_fnc+0xf0>
405064: 00000000 nop
405068: 2402ffff li v0,-1
40506c: afc20024 sw v0,36(s8)
405070: 8fc20024 lw v0,36(s8)
405074: 00000000 nop
405078: 04410006 bgez v0,405094 <toplevel_fnc+0x118>
40507c: 00000000 nop
405080: 24040001 li a0,1
405084: 24020fa1 li v0,4001
405088: 0000000c syscall
40508c: afc7001c sw a3,28(s8)
405090: afc20030 sw v0,48(s8)
405094: 00002025 move a0,zero
405098: 0c1013b4 jal 404ed0 <subroutine_fnc>
40509c: 00000000 nop
4050a0: 00021600 sll v0,v0,0x18
4050a4: 00021603 sra v0,v0,0x18
4050a8: a3c20034 sb v0,52(s8)
4050ac: 83c20034 lb v0,52(s8)
4050b0: 00000000 nop
4050b4: 1c40ffb8 bgtz v0,404f98 <toplevel_fnc+0x1c>
4050b8: 00000000 nop
4050bc: 8fc20018 lw v0,24(s8)
4050c0: 03c0e825 move sp,s8
4050c4: 8fbf003c lw ra,60(sp)
4050c8: 8fbe0038 lw s8,56(sp)
4050cc: 27bd0040 addiu sp,sp,64
4050d0: 03e00008 jr ra
4050d4: 00000000 nop
program data
build/program-mips: file format elf32-tradbigmips
Contents of section my_data:
4160e0 5c5c0000 \\..
and I wrote it in C as:
int toplevel_fnc(void) {
int a = 0;
while(1) {
char c = subroutine_fnc(0);
if (c <= 0) {
return a;
}
if (c == 92) {
a++;
int d = write(1, "\\", 2);
if (d < 0) {
exit(1);
}
} else {
int e = write(1, &c, 1);
if (e < 0) {
exit(1);
}
}
}
return a;
}
and
int subroutine_fnc(int a) {
char c;
int b = read(a, &c, 1);
if (b < 0) {
exit(1);
} else if (b == 0) {
return 0;
}
return c;
}
I am feeling lost, and also kind of stupid for asking here, but I feel like there is a small mistake that I overlooked. I've been working on this for the past three days, and I can't find the solution on how to correctly convert MIPS to C.
Please, I would be very glad if anyone could help me out on what is wrong in my code.
Thank you.

The assembly program writes two backslashes, whereas the C write(1, "\\", 2) writes one backslash and one NUL, because \\ in a string literal denotes only one backslash; you meant to write(1, "\\\\", 2).
The char is unsigned - this makes another deviation, since at a place in the assembly program a byte is sign extended and later tested with bgtz, while in the C code
char c = subroutine_fnc(0);
if (c <= 0)
the if condition will be true only for c = 0. Use signed char c … instead.

Related

C to assembly MIPS-32 [duplicate]

The MIPS assembly code generated by mips-gcc almost, but doesn't quite, run on the Mars MIPS simulator. For example:
The compiler generates "j $31" instead of "jr $31"
The compiler puts .align directives in the text segment, which Mars does not allow.
In addition, the generated assembly is not quite set up so that it will start and stop properly (i.e., no sycall 10 at the end).
These problems are all appear to be easily fixable with a simply script; but, before I re-invent the wheel, I was wondering:
(1) Are there any gcc flags that will make some of these problems go away?
(2) Does anybody know of an existing program that will fix up the mips-gcc output so that it will run on Mars?
(FWIW, I see the same behavior on both gcc 3.3.6 and 4.6.1.)
Are there any gcc flags that will make some of these problems go away?
Short answer is no. Mars uses custom system calls and is very different in calling conventions.
Does anybody know of an existing program that will fix up the mips-gcc output so that it will run on Mars?
I don't know of any automated way to convert it. You can do it only manually. I have done it actually.
Roughly, these are the steps I followed:
0. Use GobBolt compiler explorer to get a beatified raw assembly of your code. They don't use specific gcc options to get this beatified view according to this, so I'm not mentioning any gcc command, but you can set up a local copy of it.
Replace all the syscalls and their calling conventions according to this : https://courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html
Replace/add the required segment labels (such as .text, .data etc.) along with their required data.
If you have a main function (label) add j main after .text.
(4. Optionally, you can rename the registers to be more readable because as Peter Cordes mentioned in the comments, gcc for mips doesn't support the argument -mregnames)
This is an example I made, it lacks main cause it was intended as a library :
C code :
#include <stdio.h>
#include <stdlib.h>
typedef struct node Node;
struct node {
int data;
struct node *left;
struct node *right;
};
Node *new_node (int data) {
Node *ret = malloc (sizeof (Node)); ret->left = NULL;
ret->data = data;
ret->left = NULL;
ret->right = NULL;
return ret; }
void link (Node *parent, Node *left, Node *right) {
parent->left = left;
parent->right = right;
}
int depth (Node *root) {
if (root == NULL) {
return -1;
}
int left = depth (root->left);
int right = depth (root->right);
return 1 + (left > right? left : right);
}
int even_level_max (Node *root, int level) {
if (root == NULL) {
return 0x80000000;
}
int left = even_level_max(root->left, level + 1);
int right = even_level_max (root->right, level + 1);
int greater = (left > right) ? left : right;
if (level % 2 == 0) {
return (greater > root->data)? greater : root->data;
} else {
return greater;
}
}
Godbolt code :
new_node:
addiu $sp,$sp,-40
sw $31,36($sp)
sw $fp,32($sp)
move $fp,$sp
sw $4,40($fp)
li $4,12 # 0xc
jal malloc
nop
sw $2,24($fp)
lw $2,24($fp)
nop
sw $0,4($2)
lw $2,24($fp)
lw $3,40($fp)
nop
sw $3,0($2)
lw $2,24($fp)
nop
sw $0,4($2)
lw $2,24($fp)
nop
sw $0,8($2)
lw $2,24($fp)
move $sp,$fp
lw $31,36($sp)
lw $fp,32($sp)
addiu $sp,$sp,40
jr $31
nop
link:
addiu $sp,$sp,-8
sw $fp,4($sp)
move $fp,$sp
sw $4,8($fp)
sw $5,12($fp)
sw $6,16($fp)
lw $2,8($fp)
lw $3,12($fp)
nop
sw $3,4($2)
lw $2,8($fp)
lw $3,16($fp)
nop
sw $3,8($2)
nop
move $sp,$fp
lw $fp,4($sp)
addiu $sp,$sp,8
jr $31
nop
depth:
addiu $sp,$sp,-40
sw $31,36($sp)
sw $fp,32($sp)
move $fp,$sp
sw $4,40($fp)
lw $2,40($fp)
nop
bne $2,$0,$L5
nop
li $2,-1 # 0xffffffffffffffff
b $L6
nop
$L5:
lw $2,40($fp)
nop
lw $2,4($2)
nop
move $4,$2
jal depth
nop
sw $2,24($fp)
lw $2,40($fp)
nop
lw $2,8($2)
nop
move $4,$2
jal depth
nop
sw $2,28($fp)
lw $3,24($fp)
lw $2,28($fp)
nop
slt $4,$2,$3
beq $4,$0,$L7
nop
move $2,$3
$L7:
addiu $2,$2,1
$L6:
move $sp,$fp
lw $31,36($sp)
lw $fp,32($sp)
addiu $sp,$sp,40
jr $31
nop
even_level_max:
addiu $sp,$sp,-48
sw $31,44($sp)
sw $fp,40($sp)
move $fp,$sp
sw $4,48($fp)
sw $5,52($fp)
lw $2,48($fp)
nop
bne $2,$0,$L9
nop
li $2,-2147483648 # 0xffffffff80000000
b $L10
nop
$L9:
lw $2,48($fp)
nop
lw $3,4($2)
lw $2,52($fp)
nop
addiu $2,$2,1
move $5,$2
move $4,$3
jal even_level_max
nop
sw $2,24($fp)
lw $2,48($fp)
nop
lw $3,8($2)
lw $2,52($fp)
nop
addiu $2,$2,1
move $5,$2
move $4,$3
jal even_level_max
nop
sw $2,28($fp)
lw $3,24($fp)
lw $2,28($fp)
nop
slt $4,$2,$3
beq $4,$0,$L11
nop
move $2,$3
$L11:
sw $2,32($fp)
lw $2,52($fp)
nop
andi $2,$2,0x1
bne $2,$0,$L12
nop
lw $2,48($fp)
nop
lw $3,0($2)
lw $2,32($fp)
nop
slt $4,$2,$3
beq $4,$0,$L10
nop
move $2,$3
b $L10
nop
$L12:
lw $2,32($fp)
$L10:
move $sp,$fp
lw $31,44($sp)
lw $fp,40($sp)
addiu $sp,$sp,48
jr $31
nop
Converted Mars code :
# Registers:
# a : store results
# t : temporaries
# s : saved
# k : kernel
.text:
j main
new_node: #Node *new_node (int data)
# prologue
addiu $sp,$sp,-40
sw $ra,36($sp)
sw $fp,32($sp)
move $fp,$sp
sw $a0,40($fp) # fp[40] = data
li $v0, 9
li $a0, 12
syscall
sw $v0,24($fp) # fp[24] = sbrk ( sizeof (Node = 12) )
lw $v0,24($fp)
lw $v1,40($fp) # data = fp[40]
sw $v1,0($v0) # ret[0] = data;
lw $v0,24($fp)
sw $zero,4($v0) # ret[4] = NULL;
lw $v0,24($fp)
sw $zero,8($v0) # ret[8] = NULL;
# epilogue
lw $v0,24($fp)
move $sp,$fp
lw $ra,36($sp)
lw $fp,32($sp)
addiu $sp,$sp,40
jr $ra
nop
link: # int depth (Node *root)
# prologue
addiu $sp,$sp,-8
sw $fp,4($sp)
move $fp,$sp
#store arguments
sw $a0,8($fp)
sw $a1,12($fp)
sw $a2,16($fp)
#parent -> left = left;
lw $v0,8($fp)
lw $v1,12($fp)
sw $v1,4($v0)
sw $a1,4($a0)
# parent -> right = right
lw $v0,8($fp)
lw $v1,16($fp)
sw $v1,8($v0)
sw $a2,8($a0)
# epilogue
move $sp,$fp
lw $fp,4($sp)
addiu $sp,$sp,8
jr $ra
nop
depth: # int depth (Node *root)
# prologue
addiu $sp,$sp,-40
sw $ra,36($sp)
sw $fp,32($sp)
move $fp,$sp
sw $a0,40($fp) # fp[40] = root
lw $v0,40($fp)
bne $v0,$zero,L5
li $v0,-1
b L6 #if (root == NULL) return -1;
L5:
lw $v0,40($fp)
lw $v0,4($v0)
move $a0,$v0 # a0 = root -> left
jal depth # depth(a0)
sw $v0,24($fp) # fp[24] = depth(a0)
lw $v0,40($fp)
lw $v0,8($v0)
move $a0,$v0 # a0 = root -> right
jal depth # depth(a0)
sw $v0,28($fp) # fp[28] = depth(a0)
lw $v1,24($fp) # v0 = right
lw $v0,28($fp) # v1 = left
slt $a0,$v0,$v1 # a0 = v1 > v0 ? 0 : 1
beq $a0,$zero,L7
move $v0,$v1 # executed when v1 > v0
L7:
addiu $v0,$v0,1 # executed when v0 < v1
L6:
# epilogue
move $sp,$fp
lw $ra,36($sp)
lw $fp,32($sp)
addiu $sp,$sp,40
jr $ra
even_level_max:
# prologue
addiu $sp,$sp,-48
sw $ra,44($sp)
sw $fp,40($sp)
move $fp,$sp
sw $a0,48($fp) # fp[48] = root
sw $a1,52($fp) # fp[52] = level
lw $v0,48($fp)
bne $v0,$zero,L9
li $v0, 0x80000000
b L10 # if (root == NULL) return 0x80000000;
L9: # root != NULL
lw $v0,48($fp)
lw $v1,4($v0) # v1 = root -> left
lw $v0,52($fp)
addiu $v0,$v0,1 # v0 = level + 1
move $a1,$v0
move $a0,$v1
jal even_level_max
sw $v0,24($fp) # fp[24] = left = even_level_max(root -> left, level +1)
lw $v0,48($fp)
lw $v1,8($v0) # v1 = root -> right
lw $v0,52($fp)
addiu $v0,$v0,1 # v0 = level + 1
move $a1,$v0
move $a0,$v1
jal even_level_max
sw $v0,28($fp) # fp[28] = right = even_level_max(root -> right, level + 1)
lw $v1,24($fp) # v1 = right
lw $v0,28($fp) # v0 = left
slt $a0,$v0,$v1 # a0 = v1 > v0 ? 0 : 1
beq $a0,$zero,L11
move $v0,$v1
L11:
sw $v0,32($fp) # fp[32] = greater
lw $v0,52($fp) # v0 = level
andi $v0,$v0,0x1 # v0 & 1
bne $v0,$zero,L12
lw $v0,48($fp) # v0 = root
lw $v1,0($v0) # v1 = data
lw $v0,32($fp) # v0 = greater
slt $a0,$v0,$v1 # a0 = v1 > v0 ? 0 : 1
beq $a0,$zero,L10 # return greater
move $v0,$v1 # v0 = data
b L10 # return data
L12:
lw $v0,32($fp) # return greater
L10:
# epilogue
move $sp,$fp
lw $ra,44($sp)
lw $fp,40($sp)
addiu $sp,$sp,48
jr $ra

can you produce BEQL MIPS instruction with C code?

So I have this code snippet in C
int unit_test_case08(int a, int b)
{
int success = 1336;
if(a != b)
{
success = 1337;
}
else
{
success = -1;
}
return success;
}
Which translates in MIPS to
unit_test_case08:
addiu $sp,$sp,-24
sw $fp,20($sp)
move $fp,$sp
sw $4,24($fp)
sw $5,28($fp)
sw $6,32($fp)
li $2,1336 # 0x538
sw $2,8($fp)
lw $3,24($fp)
lw $2,28($fp)
nop
beq $3,$2,$L2
nop
li $2,1337 # 0x539
sw $2,8($fp)
b $L3
nop
$L2:
li $2,-1 # 0xffffffffffffffff
sw $2,8($fp)
$L3:
lw $2,8($fp)
move $sp,$fp
lw $fp,20($sp)
addiu $sp,$sp,24
jr $31
nop
But for my question, im trying to create some test cases for my emulator, but am finding it hard to generate some code in C that will get me BEQL instead of BEQ?
beq $3,$2,$L2
This question extends to most of the "Likelys" if possible.
I am a very new to MIPS.
I would like to learn how to code a test case in C that would translate to BEQL instead of BEQ.

What does %call16 and .reloc mean in mips?

I have converted a c code into mips32 using gcc compiler but there are some parts that I did not understand.
This is c code:
int main()
{
float fibSquared;
int F[10] = {0};
F[0] = 0;
F[1] = 1;
for(int i = 2; i < 10 ; i++)
F[i] = F[i-1] + F[i-2];
fibSquared = sqrt(F[9]);
printf("%f",fibSquared);
return 0;
}
This is mips code:
.file 1 ""
.section .mdebug.abi32
.previous
.nan legacy
.module fp=32
.module nooddspreg
.abicalls
.rdata
.align 2
$LC0:
.ascii "%f\000"
.text
.align 2
.globl main
.set nomips16
.set nomicromips
.ent main
.type main, #function
main:
.frame $fp,80,$31 # vars= 48, regs= 2/0, args= 16, gp= 8
.mask 0xc0000000,-4
.fmask 0x00000000,0
.set noreorder
.cpload $25
.set nomacro
addiu $sp,$sp,-80
sw $31,76($sp)
sw $fp,72($sp)
move $fp,$sp
.cprestore 16
movz $31,$31,$0
sw $0,32($fp)
sw $0,36($fp)
sw $0,40($fp)
sw $0,44($fp)
sw $0,48($fp)
sw $0,52($fp)
sw $0,56($fp)
sw $0,60($fp)
sw $0,64($fp)
sw $0,68($fp)
sw $0,32($fp)
li $2,1 # 0x1
sw $2,36($fp)
li $2,2 # 0x2
sw $2,24($fp)
b $L2
nop
$L3:
lw $2,24($fp)
nop
addiu $2,$2,-1
sll $2,$2,2
addiu $3,$fp,24
addu $2,$3,$2
lw $3,8($2)
lw $2,24($fp)
nop
addiu $2,$2,-2
sll $2,$2,2
addiu $4,$fp,24
addu $2,$4,$2
lw $2,8($2)
nop
addu $3,$3,$2
lw $2,24($fp)
nop
sll $2,$2,2
addiu $4,$fp,24
addu $2,$4,$2
sw $3,8($2)
lw $2,24($fp)
nop
addiu $2,$2,1
sw $2,24($fp)
$L2:
lw $2,24($fp)
nop
slt $2,$2,10
bne $2,$0,$L3
nop
lw $2,68($fp)
nop
mtc1 $2,$f0
nop
cvt.d.w $f0,$f0
mov.d $f12,$f0
lw $2,%call16(sqrt)($28)
nop
move $25,$2
.reloc 1f,R_MIPS_JALR,sqrt
1: jalr $25
nop
lw $28,16($fp)
cvt.s.d $f0,$f0
swc1 $f0,28($fp)
lwc1 $f0,28($fp)
nop
cvt.d.s $f0,$f0
mfc1 $7,$f0
mfc1 $6,$f1
lw $2,%got($LC0)($28)
nop
addiu $4,$2,%lo($LC0)
lw $2,%call16(printf)($28)
nop
move $25,$2
.reloc 1f,R_MIPS_JALR,printf
1: jalr $25
nop
lw $28,16($fp)
move $2,$0
move $sp,$fp
lw $31,76($sp)
lw $fp,72($sp)
addiu $sp,$sp,80
j $31
nop
.set macro
.set reorder
.end main
.size main, .-main
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"
This is the part I could not understand:
lw $2,68($fp)
nop
mtc1 $2,$f0
nop
cvt.d.w $f0,$f0
mov.d $f12,$f0
lw $2,%call16(sqrt)($28)
nop
move $25,$2
.reloc 1f,R_MIPS_JALR,sqrt
1: jalr $25
nop
lw $28,16($fp)
cvt.s.d $f0,$f0
swc1 $f0,28($fp)
lwc1 $f0,28($fp)
nop
cvt.d.s $f0,$f0
mfc1 $7,$f0
mfc1 $6,$f1
lw $2,%got($LC0)($28)
nop
addiu $4,$2,%lo($LC0)
lw $2,%call16(printf)($28)
nop
move $25,$2
.reloc 1f,R_MIPS_JALR,printf
1: jalr $25
nop
lw $28,16($fp)
move $2,$0
move $sp,$fp
lw $31,76($sp)
lw $fp,72($sp)
addiu $sp,$sp,80
j $31
nop
.set macro
.set reorder
.end main
.size main, .-main
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"
What does .reloc mean?
How does %call16 work?
What is the corresponding value of the variable fibSquared?
How the functions "printf" and "sqrt" are called and executed?
I think you take the same class I do because I have the same homework, so I am going to share what I understood myself, it may help.
For %call16, if you noticed between the brackets, the name that the C code uses from the included files such as printf from stdio.h, sqrt from math file, so it's clearly calling them so he can use them.
About the .reloc, I have noticed that they come after %call16 and the called function executed and is for relocating the memory, so I think it reorders the included files from any damage that may have happened.
The fibSquared value is located in mem[-12] (SW $3,8($2))$2=-20, then it's moved to $f0 by(mtc1 $2,$f0). In the instruction, the second par is the destination($f0). It's converted from int to float in(cvt.d.w $f0,$f0).
The sqrt executed in this part of the code:
lw $2,%call16(sqrt)($28) \\ in this particular
nop
move $25,$2
.reloc 1f,R_MIPS_JALR,sqrt
1: jalr $25
$25 at the beginning was chosen for cpload (.cpload $25)
** printf :
lw $2,%got($LC0)($28)
nop
addiu $4,$2,%lo($LC0)
lw $2,%call16(printf)($28)\\ in this particular
nop
move $25,$2
.reloc 1f,R_MIPS_JALR,printf
1: jalr $25

Can someone translate these C codes into mips assembly code

//Please transfer these C codes into Mips assembly,
//I need to do this in mips assembly,but I have troubles on doing array
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[])
{
char str[100];
printf("Input the string: ");
scanf("%s", str);
int size = (int)strlen(str);
for(int i = 0; i < size + 2; i++)
{
printf("*");
}
printf("\n");
printf("*%s*\n", str);
for(int i = 0; i < size + 2; i++)
{
printf("*");
}
printf("\n");
return 0;
}
//Thanks
You could use this http://reliant.colab.duke.edu/c2mips/ trans of c to Mips assembly. And the following should be work.
.file 1 ""
.section .mdebug.abi32
.previous
.gnu_attribute 4, 1
.abicalls
.rdata
.align 2
$LC0:
.ascii "Input the string: \000"
.align 2
$LC1:
.ascii "%s\000"
.align 2
$LC2:
.ascii "*%s*\012\000"
.text
.align 2
.globl main
$LFB0 = .
.set nomips16
.ent main
.type main, #function
main:
.frame $fp,144,$31 # vars= 112, regs= 2/0, args= 16, gp= 8
.mask 0xc0000000,-4
.fmask 0x00000000,0
.set noreorder
.cpload $25
.set nomacro
addiu $sp,$sp,-144
$LCFI0:
sw $31,140($sp)
$LCFI1:
sw $fp,136($sp)
movz $31,$31,$0
$LCFI2:
move $fp,$sp
$LCFI3:
.cprestore 16
sw $4,144($fp)
sw $5,148($fp)
lw $2,%got($LC0)($28)
nop
addiu $4,$2,%lo($LC0)
lw $2,%call16(printf)($28)
nop
move $25,$2
jalr $25
nop
lw $28,16($fp)
addiu $2,$fp,36
lw $3,%got($LC1)($28)
nop
addiu $4,$3,%lo($LC1)
move $5,$2
lw $2,%call16(scanf)($28)
nop
move $25,$2
jalr $25
nop
lw $28,16($fp)
addiu $2,$fp,36
move $4,$2
lw $2,%call16(strlen)($28)
nop
move $25,$2
jalr $25
nop
lw $28,16($fp)
sw $2,32($fp)
sw $0,28($fp)
b $L2
nop
$L3:
li $4,42 # 0x2a
lw $2,%call16(putchar)($28)
nop
move $25,$2
jalr $25
nop
lw $28,16($fp)
lw $2,28($fp)
nop
addiu $2,$2,1
sw $2,28($fp)
$L2:
lw $2,32($fp)
nop
addiu $3,$2,2
lw $2,28($fp)
nop
slt $2,$2,$3
andi $2,$2,0x00ff
bne $2,$0,$L3
nop
li $4,10 # 0xa
lw $2,%call16(putchar)($28)
nop
move $25,$2
jalr $25
nop
lw $28,16($fp)
addiu $2,$fp,36
lw $3,%got($LC2)($28)
nop
addiu $4,$3,%lo($LC2)
move $5,$2
lw $2,%call16(printf)($28)
nop
move $25,$2
jalr $25
nop
lw $28,16($fp)
sw $0,24($fp)
b $L4
nop
$L5:
li $4,42 # 0x2a
lw $2,%call16(putchar)($28)
nop
move $25,$2
jalr $25
nop
lw $28,16($fp)
lw $2,24($fp)
nop
addiu $2,$2,1
sw $2,24($fp)
$L4:
lw $2,32($fp)
nop
addiu $3,$2,2
lw $2,24($fp)
nop
slt $2,$2,$3
andi $2,$2,0x00ff
bne $2,$0,$L5
nop
li $4,10 # 0xa
lw $2,%call16(putchar)($28)
nop
move $25,$2
jalr $25
nop
lw $28,16($fp)
move $2,$0
move $sp,$fp
lw $31,140($sp)
lw $fp,136($sp)
addiu $sp,$sp,144
j $31
nop
.set macro
.set reorder
.end main
$LFE0:
.size main, .-main
.section .eh_frame,"aw",#progbits
$Lframe1:
.4byte $LECIE1-$LSCIE1
$LSCIE1:
.4byte 0x0
.byte 0x1
.globl __gxx_personality_v0
.ascii "zP\000"
.uleb128 0x1
.sleb128 -4
.byte 0x1f
.uleb128 0x5
.byte 0x0
.4byte __gxx_personality_v0
.byte 0xc
.uleb128 0x1d
.uleb128 0x0
.align 2
$LECIE1:
$LSFDE1:
.4byte $LEFDE1-$LASFDE1
$LASFDE1:
.4byte $LASFDE1-$Lframe1
.4byte $LFB0
.4byte $LFE0-$LFB0
.uleb128 0x0
.byte 0x4
.4byte $LCFI0-$LFB0
.byte 0xe
.uleb128 0x90
.byte 0x4
.4byte $LCFI2-$LCFI0
.byte 0x11
.uleb128 0x1e
.sleb128 2
.byte 0x11
.uleb128 0x1f
.sleb128 1
.byte 0x4
.4byte $LCFI3-$LCFI2
.byte 0xd
.uleb128 0x1e
.align 2
$LEFDE1:
.ident "GCC: (Debian 4.4.5-8) 4.4.5"

Floating point variable's value missing in data memory

I am a master student and currently doing my summer final project, which is about design a MIPS processor with a FPU and implement in a FPGA.
The instructions that I'm going to implement are depended on the cross-compiler I'm using. So, from a hardware designer point of view, I started the project by first looking the instructions can be generated from the compiler.
For integer design(the main core design), I wrote some C codes, here for example, a simple one:
int main ()
{
int a,b,c;
a=1;
b=2;
c=a+2;
}
A simple addition, the compiler gives assembly codes: (I just posted the assembly codes in main, because I did not plan to run a operating system on my MIPS)
00400168 <main>:
400168: 27bdffe8 addiu sp,sp,-24
40016c: afbe0010 sw s8,16(sp)
400170: 03a0f021 move s8,sp
400174: 24020001 li v0,1
400178: afc20008 sw v0,8(s8)
40017c: 24020002 li v0,2
400180: afc20004 sw v0,4(s8)
400184: 8fc20008 lw v0,8(s8)
400188: 00000000 nop
40018c: 20420002 addi v0,v0,2
400190: afc20000 sw v0,0(s8)
400194: 03c0e821 move sp,s8
400198: 8fbe0010 lw s8,16(sp)
40019c: 27bd0018 addiu sp,sp,24
4001a0: 03e00008 jr ra
I like to understand the assembly code, that can helps me more understand MIPS architecture, and based on the instructions order I can design a hazard detection unit based on the compiler.
We can see from those 4 instruction:
400174: 24020001 li v0,1
400178: afc20008 sw v0,8(s8)
40017c: 24020002 li v0,2
400180: afc20004 sw v0,4(s8)
The compiler loads 1, 2 into variable a, b.
For the integer assembly code, I can understand no problems.
Ok, lets go to the floating point unit, as the same, I wrote a very similar C :
Floating point testing C code
void main ()
{
float a,b,c;
a=1;
b=2;
c=a+b;
}
Now the assembly codes are much different:
00400168 <main>:
400168: 27bdffe8 addiu sp,sp,-24
40016c: afbe0010 sw s8,16(sp)
400170: 03a0f021 move s8,sp
400174: c7808004 lwc1 $f0,-32764(gp)
400178: 00000000 nop
40017c: e7c00008 swc1 $f0,8(s8)
400180: c7808008 lwc1 $f0,-32760(gp)
400184: 00000000 nop
400188: e7c00004 swc1 $f0,4(s8)
40018c: c7c20008 lwc1 $f2,8(s8)
400190: c7c00004 lwc1 $f0,4(s8)
400194: 00000000 nop
400198: 46001000 add.s $f0,$f2,$f0
40019c: e7c00000 swc1 $f0,0(s8)
4001a0: 03c0e821 move sp,s8
4001a4: 8fbe0010 lw s8,16(sp)
4001a8: 27bd0018 addiu sp,sp,24
4001ac: 03e00008 jr ra
4001b0: 00000000 nop
Doesn't like pervious code, those 6 instructions looks like the program load the variable's value from data memory instead using instruction li:
400174: c7808004 lwc1 $f0,-32764(gp)
400178: 00000000 nop
40017c: e7c00008 swc1 $f0,8(s8)
400180: c7808008 lwc1 $f0,-32760(gp)
400184: 00000000 nop
400188: e7c00004 swc1 $f0,4(s8)
Here comes the problem, I just can not figure out what is value stored in -32764(gp) and f0,-32760(gp), because there are not any SW instructions that try to store data into those address.
Here is the fully assembly code generated by compiler:
floatadd: file format elf32-bigmips
Disassembly of section .init:
00400018 <_init>:
400018: 27bdffe0 addiu sp,sp,-32
40001c: afbf0014 sw ra,20(sp)
400020: 0c10003a jal 4000e8 <frame_dummy>
400024: 00000000 nop
400028: 0c10006d jal 4001b4 <__do_global_ctors_aux>
40002c: 00000000 nop
400030: 8fbf0014 lw ra,20(sp)
400034: 27bd0020 addiu sp,sp,32
400038: 03e00008 jr ra
40003c: 00000000 nop
Disassembly of section .text:
00400040 <_ftext>:
400040: 27bdffe0 addiu sp,sp,-32
400044: afb10014 sw s1,20(sp)
400048: 3c110040 lui s1,0x40
40004c: 9222126c lbu v0,4716(s1)
400050: afbf0018 sw ra,24(sp)
400054: 14400019 bnez v0,4000bc <_ftext+0x7c>
400058: afb00010 sw s0,16(sp)
40005c: 3c100040 lui s0,0x40
400060: 8e021260 lw v0,4704(s0)
400064: 00000000 nop
400068: 8c430000 lw v1,0(v0)
40006c: 00000000 nop
400070: 10600009 beqz v1,400098 <_ftext+0x58>
400074: 24420004 addiu v0,v0,4
400078: 0060f809 jalr v1
40007c: ae021260 sw v0,4704(s0)
400080: 8e021260 lw v0,4704(s0)
400084: 00000000 nop
400088: 8c430000 lw v1,0(v0)
40008c: 00000000 nop
400090: 1460fff9 bnez v1,400078 <_ftext+0x38>
400094: 24420004 addiu v0,v0,4
400098: 3c020000 lui v0,0x0
40009c: 24420000 addiu v0,v0,0
4000a0: 10400005 beqz v0,4000b8 <_ftext+0x78>
4000a4: 24020001 li v0,1
4000a8: 3c040040 lui a0,0x40
4000ac: 0c000000 jal 0 <_init-0x400018>
4000b0: 24840244 addiu a0,a0,580
4000b4: 24020001 li v0,1
4000b8: a222126c sb v0,4716(s1)
4000bc: 8fbf0018 lw ra,24(sp)
4000c0: 8fb10014 lw s1,20(sp)
4000c4: 8fb00010 lw s0,16(sp)
4000c8: 03e00008 jr ra
4000cc: 27bd0020 addiu sp,sp,32
004000d0 <call___do_global_dtors_aux>:
4000d0: 27bdffe8 addiu sp,sp,-24
4000d4: afbf0010 sw ra,16(sp)
4000d8: 8fbf0010 lw ra,16(sp)
4000dc: 00000000 nop
4000e0: 03e00008 jr ra
4000e4: 27bd0018 addiu sp,sp,24
004000e8 <frame_dummy>:
4000e8: 3c020000 lui v0,0x0
4000ec: 27bdffe8 addiu sp,sp,-24
4000f0: 3c040040 lui a0,0x40
4000f4: 3c050040 lui a1,0x40
4000f8: 24420000 addiu v0,v0,0
4000fc: afbf0010 sw ra,16(sp)
400100: 24840244 addiu a0,a0,580
400104: 10400003 beqz v0,400114 <frame_dummy+0x2c>
400108: 24a51270 addiu a1,a1,4720
40010c: 0c000000 jal 0 <_init-0x400018>
400110: 00000000 nop
400114: 3c040040 lui a0,0x40
400118: 8c831258 lw v1,4696(a0)
40011c: 3c020000 lui v0,0x0
400120: 10600007 beqz v1,400140 <frame_dummy+0x58>
400124: 24590000 addiu t9,v0,0
400128: 24841258 addiu a0,a0,4696
40012c: 13200004 beqz t9,400140 <frame_dummy+0x58>
400130: 00000000 nop
400134: 8fbf0010 lw ra,16(sp)
400138: 03200008 jr t9
40013c: 27bd0018 addiu sp,sp,24
400140: 8fbf0010 lw ra,16(sp)
400144: 00000000 nop
400148: 03e00008 jr ra
40014c: 27bd0018 addiu sp,sp,24
00400150 <call_frame_dummy>:
400150: 27bdffe8 addiu sp,sp,-24
400154: afbf0010 sw ra,16(sp)
400158: 8fbf0010 lw ra,16(sp)
40015c: 00000000 nop
400160: 03e00008 jr ra
400164: 27bd0018 addiu sp,sp,24
00400168 <main>:
400168: 27bdffe8 addiu sp,sp,-24
40016c: afbe0010 sw s8,16(sp)
400170: 03a0f021 move s8,sp
400174: c7808004 lwc1 $f0,-32764(gp)
400178: 00000000 nop
40017c: e7c00008 swc1 $f0,8(s8)
400180: c7808008 lwc1 $f0,-32760(gp)
400184: 00000000 nop
400188: e7c00004 swc1 $f0,4(s8)
40018c: c7c20008 lwc1 $f2,8(s8)
400190: c7c00004 lwc1 $f0,4(s8)
400194: 00000000 nop
400198: 46001000 add.s $f0,$f2,$f0
40019c: e7c00000 swc1 $f0,0(s8)
4001a0: 03c0e821 move sp,s8
4001a4: 8fbe0010 lw s8,16(sp)
4001a8: 27bd0018 addiu sp,sp,24
4001ac: 03e00008 jr ra
4001b0: 00000000 nop
004001b4 <__do_global_ctors_aux>:
4001b4: 3c020040 lui v0,0x40
4001b8: 2442124c addiu v0,v0,4684
4001bc: 8c44fffc lw a0,-4(v0)
4001c0: 27bdffe0 addiu sp,sp,-32
4001c4: 2403ffff li v1,-1
4001c8: afb00010 sw s0,16(sp)
4001cc: afbf0018 sw ra,24(sp)
4001d0: afb10014 sw s1,20(sp)
4001d4: 10830008 beq a0,v1,4001f8 <__do_global_ctors_aux+0x44>
4001d8: 2450fffc addiu s0,v0,-4
4001dc: 2411ffff li s1,-1
4001e0: 0080f809 jalr a0
4001e4: 2610fffc addiu s0,s0,-4
4001e8: 8e040000 lw a0,0(s0)
4001ec: 00000000 nop
4001f0: 1491fffb bne a0,s1,4001e0 <__do_global_ctors_aux+0x2c>
4001f4: 00000000 nop
4001f8: 8fbf0018 lw ra,24(sp)
4001fc: 8fb10014 lw s1,20(sp)
400200: 8fb00010 lw s0,16(sp)
400204: 03e00008 jr ra
400208: 27bd0020 addiu sp,sp,32
0040020c <call___do_global_ctors_aux>:
40020c: 27bdffe8 addiu sp,sp,-24
400210: afbf0010 sw ra,16(sp)
400214: 8fbf0010 lw ra,16(sp)
400218: 00000000 nop
40021c: 03e00008 jr ra
400220: 27bd0018 addiu sp,sp,24
Disassembly of section .fini:
00400224 <_fini>:
400224: 27bdffe0 addiu sp,sp,-32
400228: afbf0014 sw ra,20(sp)
40022c: 0c100010 jal 400040 <_ftext>
400230: 00000000 nop
400234: 8fbf0014 lw ra,20(sp)
400238: 27bd0020 addiu sp,sp,32
40023c: 03e00008 jr ra
400240: 00000000 nop
I am not good at MIPS assembly, can someone explain where are the floating point variable' value 1 and 2?
About your question
ELF executables can have one or more sections filled with the static data (string, floating point numbers, numbers, whatever) used by the program.
This sections are loaded into memory by the loader with the rest of the program, thereby avoiding intermixing code and data and reducing the code size.
For the ELF on MIPS systems you should refer to this where there is this nice picture:
As you can see $gp is used to address the section .sdata and .sbss, where the initial s stands for small.
All these efforts are taken to minimize code size as by using $gp the compiler can generate 16 bit offsets (versus the 32 bit ones normally used).
Since the offset is signed, $gp is placed in the middle of a (at most) 64 KiB region formed by .sdata + .sbss.
Your floating points value are not coded directly in the instructions because FP instruction does not takes immediates, instead they are saved into a readonly section and loaded from there.
About your purpose
Why in the end do you care about this?
If your goal is to design an implementation of the MIPS ISA, just pick the specific ISA (MIPS32 I? MIPS32 IV? MIPS 64?), get the documents, get the whole picture and implement a microarchitecture for it.
If an instruction is a valid instruction according to your chosen ISA then your implementation must be able to execute it, don't worry about what the compilers are doing, they are grown up, they can take care of them selves and in the end if the code you are executing is broken, who cares? As long it is valid.
These will help you:
MIPS32™ Architecture For Programmers Volume I: Introduction to the MIPS32™ Architecture
MIPS32™ Architecture For Programmers Volume II: The MIPS32™ Instruction Set

Resources