Compile code in C to MIPS assembly - c

I wrote a C program that I need to see it in MIPS assembly code.
How do I install or operate a software that takes *.c file to be *.txt or *.something_else to see its MIPS assembly code ?
My OS is Linux.
Thanks a lot !!
BTW my code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 128
int main ()
{
char mychar , string [SIZE];
int i;
int count =0 ;
printf ("Please enter your string: \n\n");
fgets (string, SIZE, stdin);
printf ("Please enter char to find: ");
mychar = getchar();
for (i=0 ; string[i] != '\0' ; i++ )
if ( string[i] == mychar )
count++;
printf ("The char %c appears %d times\n" ,mychar ,count);
return 0;
}

What you want is a MIPS cross-compiler, unless you're running Linux on a MIPS box, in which case you want a regular MIPS compiler. Here is a howto for setting up a cross compiler on Linux.
Once you've compiled it, you'll want to see the MIPS disassembly. objdump can help you there.

You need to install a MIPS cross-compile library, and then you need to pass -S and one of the -march=mips* options to gcc.

You can use Dan Kegels' excellent and easy to use cross-tool to compile your own MIPS cross compiler.

Related

undefined reference to getdelim() error (Windows) (C Language)

I am trying to work with getdelim() function which apperantly is the preferred method with getline() over fgets(). However, when I try to run the code below, I get undefined reference to getdelim() error.
I don't think it has anything to do with the code but rather the gcc version that I am using. So to the cmd I typed gcc -v and apperantly I have gcc version 8.1.0 (x86_64-win32-seh-rev0, Built by MinGW-W64 project)
I am not sure how old it is or if that's the problem. If so, what version of the gcc should I use and can I solve this with adding some fancy macros?
Code:
#include <stdio.h>
int main()
{
int size = 10;
char *string;
printf ("Please enter a string: ");
string = (char*)malloc(size);
getdelim (&string, &size, '-', stdin);
printf( "%s\n", string );
return 0;
}

I'm implementing printf function in C/Linux

Program:
#ifndef PRINTF_H
#define PRINTF_H
#include "my_put_char.h"
int my_printf(char *str, ...);
#endif
This is my Header file for my function.
#include <stdio.h>
#include "my_put_char.h"
void my_put_char(char c)
{
fwrite(&c, sizeof(char), 1, stdout);
}
This is my putchar implementation(my_put_char.c).
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "printf.h"
int my_printf(char *str, ...)
{
if(str == NULL)
return 0;
int i;
char a;
va_list print;
va_start(print,str);
for(i = 0; str[i] ; i++)
{
if(str[i] == '%')
{
i++;
switch(str[i])
{
case 'c':
a = va_arg(print, char);
my_put_char(a);
break;
}
}
}
va_end(print);
return 0;
}
At last, this is a part of my printf implementation.
I'm testing with %c to display a character.
When I do my_print("%c", 'd'); from main.c
it compiles and displays d.
But when I do my_print("%c", "hi"); , it still compiles and displays a number.
Question:
After(or before) writing a = va_arg(print, char); Is there a way to check whether my input is a different data type?
I'm trying to display an error if my input is a different data type.
I'm on this subject for 2 days and couldn't find any answer.
Thank you so much for your time!
when I do my_print("%c", "hi"); , it still compiles and displays a number
You've got some undefined behavior, so be scared. Your my_printf would call va_arg with an argument of the bad type (expected char promoted to int, got char*).
To explain what is happening you should dive into implementation details (look into the assembler code, e.g. with gcc -Wall -fverbose-asm -O -S; study your processor, its instruction set architecture, its application binary interface and calling conventions). You don't want to do that, it could take years and is not reproducible.
Read absolutely Lattner's blog on UB, right now!
Then download C11 specification n1570....
You could also, with gcc, use some function attributes. Don't forget to compile with all warnings and debug info (gcc -Wall -Wextra -g)
after writing a = va_arg(print, char); Is there a way to check whether my input is a different data type?
No, not really and not always. But the format function attribute could help. And you could also spend months customizing GCC with your own plugin or some GCC MELT extension (that is not worth your time). Be aware of the Halting Problem and Rice's Theorem (each makes static source code program analysis so challenging). Look also into source analyzing tools like Frama-C.
I'm implementing printf function
BTW studying the source code of existing free software implementations of the C standard library (such as GNU glibc and musl-libc) could be inspirational; they are based upon syscalls(2).

Cannot run program

I started learning C programming with C Programming Language by Denis M Ritchie I am trying to execute program from that book
#include <stdio.h>
/* count lines in input */
main()
{
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
getchar();
}
However all I get is blank console and when I type text and press enter,no value is displayed.
I am using Visual Studio 2013 IDE.
The program you posted here is for counting number of lines.
Q. However all I get is blank console and when I type text and press
enter,no value is displayed
A. Yes it shows nothing because while ((c = getchar()) != EOF) waits until you enter EOF (use ctrl + z then you will get number for lines).
getchar(c);
See declaration of getchar.
int getchar(void)
It doesn't take any parameter. Didn't it gave you error.
And main should be int main.
There are several issues. First, main has to have a type, usually int
- main()
+ int main()
and your program should return an exit status
Secondly getchar takes no arguments, and returns the input
http://www.tutorialspoint.com/c_standard_library/c_function_getchar.htm
- getchar(c)
+ c = getchar()
You can compile your program by calling
gcc -Wall test.c -o test
Where test.c is your code, and test is the binary. -Wall will show all the "warning" (errors that don't interfere with the program execution)
I believe that you use Windows, it's better to add:
system("pause");
Moreover to use system("pause"), only in Windows, you need to include another library:
#include <stdlib.h>
You can see your results but the problem here, is that you have an infinite loop. Yo need to check the \n, count and when you have a specific number, you leave from the loop.

convert c language to IA32 assembly language

I wrote a c code: convert integer to string and have a comma every 3 digits, and can anyone give me a hint how to convert it to assembly language???
I just want simply convert it into assembly language! Can't use other library call!
#include <stdio.h>
char *my_itoa(int n, char *buf)
{
int i, j, k=0, l=0;
char tmp[32] = {0};
i = n;
do {
j = i%10;
i = i/10;
sprintf(tmp+k, "%d", j);
k++;
l++;
if (i!=0 && l%3 == 0) {
sprintf(tmp+k, ",");
k++;
l = 0;
}
}while(i);
for (k--,i=0; i<=k; i++) {
buf[i] = tmp[k-i];
}
return buf;}
If your complier is gcc, this answer suggests a nice way to produce a combined C/assembly language file that is easier to read than plain assembly. They use c++, but just replace c++ with gcc:
# create assembler code:
gcc -S -fverbose-asm -g original.c -o assembly.s
# create asm interlaced with source lines:
as -alhnd assembly.s > listing.lst
C compilers conforming to the SUSv2 (Single Unix Specification version 2 published in 1997) can do what you want much more simply by using a locale flag specifier. Here's example C code that works with gcc:
#include <stdio.h>
#include <locale.h>
int main()
{
int num = 12345678;
setlocale(LC_NUMERIC, "en_US");
printf("%'d\n", num);
return 0;
}
This prints 12,345,678. Note, too, that this works correctly with negative numbers while your code does not. Because the code is simply a single library call, it's probably not worth implementing in assembly language, but if you still cared to, you could use this:
In the .rodata section include this string constant:
.fmt:
.string "%'d\n"
The code is extremely simple because all the hard work is done within printf:
; number to be converted is in %esi
movl $.fmt, %edi
movl $0, %eax
call printf

Beginner C programmer having problems with string functions

I'm a C noob, going back to school for my masters in CS so I'm taking some time to ramp up my skills. I wanted to see if anybody could lend some assistance on why I'm having problems compiling the following code. I've been following the videos on WiBit.net and develop on a 64 bit Linux environment (Ubuntu 13.10). I am using gedit and the gcc compiler no IDE.
This code runs on my Win 7 VM without errors, however when I try to execute it on my host Linux environment I'm getting errors:
Source Code: This example calls the strcmp and strcmpi functions
#include <stdio.h>
#include <string.h>
int main()
{
char str1[255];
char str2[255];
printf("str1: "); gets(str1);
printf("str2: "); gets(str2);
if(strcmp(str1, str2) == 0)
printf("Strings match exactly!");
else if(strcmpi(str1, str2) == 0)
printf("Strings match when ignoring case!");
return 0;
}
Error Message (Linux ONLY):
$gcc main.c -o demo -lm -pthread -lgmp -lreadline 2>&1
/tmp/ccwqdQMN.o: In function main':
main.c:(.text+0x25): warning: thegets' function is dangerous and should not be used.
main.c:(.text+0x8f): undefined reference to `strcmpi'
collect2: error: ld returned 1 exit status
Source Code 2: This example uses the strupr and strlwr functions
#include <stdio.h>
#include <string.h>
int main()
{
char str1[255];
char str2[255];
printf("str1: "); gets(str1);
printf("str2: "); gets(str2);
strlwr(str1);
strupr(str2);
puts (str1);
puts (str2);
return 0;
}
Error Message (Linux ONLY):
$gcc main.c -o demo -lm -pthread -lgmp -lreadline 2>&1
/tmp/ccWnIfnz.o: In function main':
main.c:(.text+0x25): warning: thegets' function is dangerous and should not be used.
main.c:(.text+0x57): undefined reference to strlwr'
main.c:(.text+0x6b): undefined reference tostrupr'
collect2: error: ld returned 1 exit status
I would love a detailed explanation if someone is willing to help and not tear me apart haha. I know that for best practices we shouldn't use gets due to buffer overflow (for example the user enters a 750 character string). Best practices would use fgets instead but my question is whether I'm getting these errors because these functions aren't part of ANSI C or what. They do show up in the man files on my machine which is throwing me through a loop.
Thanks in advance!
UPDATE:
You guys are awesome. Took all of your advice and comments and was able to revise and make a sample program for string comparison as well as conversion to upper/lower. Glad I was able to get it running on both OSes error free as well.
Sample code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
char str[255];
printf("Enter a string: "); fgets(str,255, stdin);
printf("Here is your original string, my master: %s\n", str);
//Now let's loop through and convert this to all lowercase
int i;
for(i = 0; str[i]; i++)
{
str[i] = tolower(str[i]);
}
printf("Here is a lowercase version of your string, my master: %s\n", str);
//Now we'll loop through and convert the string to uppercase
int j;
for(j = 0; str[j]; j++)
{
str[j] = toupper(str[j]);
}
printf("Here is a uppercase version of your string, my master: %s\n", str);
return 0;
}
strcmpi problem: strcasecmp() is the posix standard and so is it in linux.
strupr and strlwr doesn't exist in glibc, although you can implement them with a single line of code, as this:
c - convert a mixed-case string to all lower case
In the compilation, first you can find a warning, because the gcc doesn't find the functions in the included header. In such cases it thinks they are declared as int funcname(void). But later, while linking, it can't find the exported symbols of this nonexistant functions, and thus it can't create the executable. This second error is what stops the compilation.
There are too many difference in the c apis, although the posix standard handles them, microsoft don't follow it.
As you noted, the gets function is unsafe because it does not perform any boundary checking: you have called it with a 255-character string buffer, but if another program wrote a line longer than 255 characters, it could write data into your process's stack, and thereby cause your process to execute malicious code (or at the very least produce a segmentation fault).
Use fgets instead:
printf("str1: "); fgets(str1, 255, stdin);
printf("str2: "); fgets(str2, 255, stdin);
If you read the error output from the compiler carefully, you'll note that it's not issuing an error on your use of gets but a warning. Your code should still compile and execute if you fix the strcmpi call.

Resources