I have a code which performs the 32 bit addition of two numbers.I am generating 10 random 32 bit numbers and each of them are stored in two separate files as their corresponding hex values.The result is also stored in another file in the same way on the execution of the code i am getting some negative values for certain combinations.
Here is my code.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define TARGET_MAX 2147483647L
void main ()
{
int32_t A[10] = {0};
int32_t B[10] = {0};
int32_t S[10] = {0};
int i =0;
int n =10;
char hex[32] ={0};
time_t t;
FILE *fp = NULL;
FILE *fp1 = NULL;
FILE *fp2 = NULL;
fp = fopen("A.txt","w");
fp1 = fopen("B.txt","w");
fp2 = fopen("S.txt","w");
srand((unsigned) time(&t));
for(i=0;i<n;i++)
{
A[i] = rand() % TARGET_MAX;
if(fp != NULL)
{
sprintf(hex,"%x",A[i]);
fprintf(fp,"%s\n",hex);
memset(hex,0,sizeof(hex));
}
B[i] = rand() % TARGET_MAX;
if(fp1 != NULL)
{ sprintf(hex,"%x",B[i]);
fprintf(fp1,"%s\n",hex);
memset(hex,0,sizeof(hex));
}
S[i] = A[i] + B[i];
if(fp2 != NULL)
{ sprintf(hex,"%x",S[i]);
fprintf(fp2,"%s\n",hex);
memset(hex,0,sizeof(hex));
}
printf(" %d + %d = %d \n\r",A[i],B[i],S[i]);
}
fclose(fp);
fclose(fp1);
fclose(fp2);
}
Here is my output
vu2swz#PPDP01:~/vlsi_lab/exp6$ gcc add.c -o add
vu2swz#PPDP01:~/vlsi_lab/exp6$ ./add
1000086044 + 1204997665 = -2089883587
436835310 + 1696128436 = 2132963746
1624838244 + 335108562 = 1959946806
1782944281 + 1013582119 = -1498440896
1491331491 + 1257744454 = -1545891351
1676611730 + 773175875 = -1845179691
422206991 + 2136514004 = -1736246301
1622400103 + 152657712 = 1775057815
809410550 + 1662804335 = -1822752411
1396954314 + 742609108 = 2139563422
You're running into overflow.
In the instances where you're getting a negative number, the result is overflowing what can fix in a signed 32 bit integer.
Since the numbers you're generating are smaller than 231, their sum will be less than 232 which will fit in an unsigned 32 bit integer. So change your types to uint32_t and use the %u format specifier to print them.
Related
I'm playing around doing a few challenges of reverse engineering with ghidra.
I have analyzed a bin file, which should contain some information about a password.
When you run the file, you can give it some input, and it will check if it's the correct password.
Here is the pseudo-c code that is responsible for doing this (The comments are me):
__isoc99_scanf(&DAT_00400a82,local_28); // input scanned from user
__s2 = (char *)FUN_0040078d(0x14); // password retrieved from function
iVar1 = strcmp(local_28,__s2); // comparing strings
if (iVar1 == 0) { // if they are equal, do this
FUN_00400978(&local_48);
}
Ok, so i tried looking up the function FUN_0040078d:
void * FUN_0040078d(int param_1)
{
int iVar1;
time_t tVar2;
void *pvVar3;
int local_c;
tVar2 = time((time_t *)0x0);
DAT_00601074 = DAT_00601074 + 1;
srand(DAT_00601074 + (int)tVar2 * param_1);
pvVar3 = malloc((long)(param_1 + 1));
if (pvVar3 != (void *)0x0) {
local_c = 0;
while (local_c < param_1) {
iVar1 = rand();
*(char *)((long)local_c + (long)pvVar3) = (char)(iVar1 % 0x5e) + '!';
local_c = local_c + 1;
}
*(undefined *)((long)pvVar3 + (long)param_1) = 0;
return pvVar3;
}
/* WARNING: Subroutine does not return */
exit(1);
}
So theres a lot of information here. But overall, what I think happens is that an array of chars is constructed, by doing the operation:
(char)(iVar1 % 0x5e) + '!';
Which I have no idea what means (what does modulo on chars do? and does + '!' ) just mean concatenate a "!".
Overall I'm haivng some issues reading this, and I'm wondering if it's possible to predict what this function would output for specific inputs. In this case the function is given 14 as input.
Maybe the use of the rand() means that it cannot be deconstructed?
Can anyone give a guess/tell me whatthis function would likely output for input 14?
you got to remember that every char is a character representation of an 8bit value. Thus every operator is valid within the realm of chars.
I made this example for you to understand it better.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char character = 'A'; // 65 in dec
char bang = '!'; // 33 in dec
printf("'A' in dec: %d\n", (int)character);
printf("'!' in dec: %d\n", (int)bang);
// now the modulo operator works the same in chars
character = 'a';
char new_value = (char)character%64;
printf("a %% 64 : char_value: %c, int_value: %d\n", new_value, (int)new_value);
// you got to remember that chars are just a coded 8bit value
char at_symbol = '#'; // 64 in dec
// now the modulo operator works the same in chars
character = 'a';
new_value = (char)character%at_symbol;
printf("a %% # : char_value: %c, int_value: %d\n", new_value, (int)new_value);
// it works the same with every other operator
int value1 = 300; //this is your random value
char hex_value = 0x5E; //94 in dec or ^ in char
new_value = (char)(value1%hex_value); //300 % 94 = 18;
new_value += bang; //18 + 33 = 51 in dec or the number 3 symbol in char;
printf("dec_val: %d, char encoding: %c\n", (int)new_value, new_value);
}
as per your previous comment, here's a simplified version of your function
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
long GLOBAL_COUNTER = 0;
typedef char undefined;
void * array_constructor(int size);
int main(int argc, char **argv)
{
char* random_string = (char*)array_constructor(0x14);
printf("%s", random_string);
free(random_string);
}
void * array_constructor(int size)
{
int random_value;
//time_t cur_time;
void *array;
int counter;
//cur_time = time(NULL);
GLOBAL_COUNTER = GLOBAL_COUNTER + 1;
srand(0);//srand(GLOBAL_COUNTER + (int)cur_time * param_1);
array = malloc((long)(size + 1));//returns a void array of param_1 + 1 elements
if (array == NULL)
exit(1);
counter = 0;
while (counter < size) {
random_value = rand();
int char_value = (char)(random_value % 0x5e) + '!';//Range of possible values 33-127
// This is due to the fact that random value can have any value given the seed
// but its truncated to a modulo 0x5e so its new range is 0 - 0x5e(94 in dec)
// and you add the bang symbol at the end so 0 + 33 = 33 and 94 + 33 = 127
*(char *)((long)counter + (long)array) = char_value;
// this statement is the same as
// array[counter] = char_value
counter++;
}
*(undefined *)((long)array + (long)size) = 0; //it puts the \0 at the end of the string
return array;
}
now the only problem that you had was with the undefined typedef. this code is a simplification of yours. but it works.
I have a simple program in which program receive input from the file and converts decimal to binary and counts number of ones in its binary form?
Now For small values it is okay
and for huge values like 15755645551 , it's obviously not working
anyone has any idea how to resolve this problem?
anyone can try with my code?
thank you!!
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#define BUFFER 25
long number_read = 0;
long number_of_ones = 0;
long remainder_value = 0;
long binary = 0;
long base = 0;
long buff[BUFFER];
int main()
{
FILE *fp; //file pointer fp
fp = fopen("File.txt", "r+");
while (fgets(buff, sizeof(buff), fp) != NULL)
{
number_read = atoi(buff); //ASCII to integer
printf("\nnumber is=%d", number_read);
while (number_read > 0)
{
remainder_value = number_read % 2;
/* To count no.of 1s */
if (remainder_value == 1)
{
number_of_ones++;
}
binary = binary + remainder_value * base;
number_read = number_read / 2;
base = base * 10;
}
printf("\nNo.of 1's in It's binary representation is = %d\n", number_of_ones);
number_of_ones = 0;
}
fclose(fp);
return 0;
}
Because "long" type occupies 4 bytes as "int" type. You should change it to "long long" type.
I am trying to create a script that will convert decimals to binary based on specified size and then reverse the process, meaning from binary to decimal. So far the script and the output from my point of view (beginner) the script looks correct. I can convert all numbers from decimal to binary and vice versa. I am stack on the last part, that I am trying to convert the epoch time from a 64 bit binary number to decimal. I can not understand where I am going wrong since the rest of the numbers seem to recovered correctly. The source points that I found the scripts that I am using are Binary to Decimal and Decimal to Binary.
Update: modified code to short version:
I have modified the code to simply demonstrate the problem. The code works fine up to 32 bit binary conversion. But since I need to convert up to 64 I do not know how to do that. I noticed that because I used before int I reached the maximum limitations 32 bits, so I modified that to long long int to reach the 64 bit.
I have provided a sample of simple conversion of decimal as 1 in 32 bit format and 64 that demonstrate the problem. The epoch time is the desired output but I need to verify that the code works before I attempt the conversion.
Sample of code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <inttypes.h>
#define MAX_CHARACTERS 65
typedef struct rec {
char transmit[MAX_CHARACTERS];
char receive[MAX_CHARACTERS];
}RECORD;
char *decimal_to_binary(int n , int num); /* Define function */
char *decimal_to_binary(int n , int num) {
long long int c, d, count;
char *pointer;
count = 0;
pointer = (char*) malloc( num + 1 );
if ( pointer == NULL )
exit(EXIT_FAILURE);
for ( c = num - 1; c >= 0; c-- ) {
d = n >> c;
if ( d & 1 )
*( pointer + count ) = 1 + '0';
else
*( pointer + count ) = 0 + '0';
count++;
}
*( pointer + count ) = '\0';
return pointer;
}
int binary_decimal(long long int n); /* Define function */
int binary_decimal(long long int n) { /* Function to convert binary to decimal.*/
int decimal=0, i=0, rem;
while (n!=0) {
rem = n%10;
n/=10;
decimal += rem*pow(2,i);
++i;
}
return decimal;
}
int main(void) {
RECORD *ptr_record;
ptr_record = (RECORD *) malloc (sizeof(RECORD));
if (ptr_record == NULL) {
printf("Out of memmory!\nExit!\n");
exit(0);
}
int LI_d = 1;
char *LI_b = decimal_to_binary(LI_d,32);
memset( (*ptr_record).transmit , '\0' , sizeof((*ptr_record).transmit) );
strncat((*ptr_record).transmit , LI_b , strlen(LI_b) );
printf("LI: %s\n",(*ptr_record).transmit);
//transmit and receive
memset( (*ptr_record).receive , '\0' , sizeof((*ptr_record).receive) );
strncpy( (*ptr_record).receive , (*ptr_record).transmit , strlen((*ptr_record).transmit) );
char *LI_rcv_b = strndup( (*ptr_record).receive , 64 );
int LI_rcv_i = atoi (LI_rcv_b);
int final_LI = binary_decimal(LI_rcv_i);
printf("Final_LI: %i\n",final_LI);
free( ptr_record );
return 0;
}
Sample of output for 32 bit conversion:
LI: 00000000000000000000000000000001
Final_LI: 1
Sample of output for 64 bit conversion:
LI: 0000000000000000000000000000000100000000000000000000000000000001
Final_LI: -1
decimal_to_binary(int n, ...): better to use unsigned math
//char *decimal_to_binary(int n, int num) {
char *decimal_to_binary(unsigned long long n, int num) {
// long long int c, d, count;
unsigned long long int d;
int c, count;
char *pointer;
count = 0;
pointer = malloc(num + 1); // drop cast
if (pointer == NULL)
exit(EXIT_FAILURE);
for (c = num - 1; c >= 0; c--) {
d = n >> c;
if (d & 1)
*(pointer + count) = 1 + '0';
else
*(pointer + count) = 0 + '0';
count++;
}
*(pointer + count) = '\0';
return pointer;
}
Simplify binary_decimal(). Again use unsigned math, drop pow()
/* Function to convert binary to decimal.*/
unsigned long binary_decimal(unsigned long long int n) {
unsigned long decimal = 0;
while (n != 0) {
decimal *= 2;
decimal += n % 10;
n /= 10;
}
return decimal;
}
main() has lots of issues
int main(void) {
RECORD *ptr_record;
ptr_record = malloc(sizeof(RECORD)); // drop cast
if (ptr_record == NULL) {
printf("Out of memory!\nExit!\n"); // spelling fix
exit(0);
}
// use unsigned long long
unsigned long long LI_d = 1;
LI_d = (unsigned long long) -1;
char *LI_b = decimal_to_binary(LI_d, 32);
memset((*ptr_record).transmit, '\0', sizeof((*ptr_record).transmit));
// strncat((*ptr_record).transmit, LI_b, strlen(LI_b));
strncat((*ptr_record).transmit, LI_b, sizeof((*ptr_record).transmit) - 1);
printf("LI: %s\n", (*ptr_record).transmit);
//transmit and receive
memset((*ptr_record).receive, '\0', sizeof((*ptr_record).receive));
// strncpy((*ptr_record).receive, (*ptr_record).transmit, strlen((*ptr_record).transmit));
strncpy((*ptr_record).receive, (*ptr_record).transmit, sizeof((*ptr_record).transmit) - 1);
// char *LI_rcv_b = strndup((*ptr_record).receive, 64);
char *LI_rcv_b = strndup((*ptr_record).receive, MAX_CHARACTERS);
// At this point, approach is in error
// Cannot take a 64-decimal digit string and convert to a typical long long.
// int LI_rcv_i = atoi(LI_rcv_b);
// int final_LI = binary_decimal(LI_rcv_i);
// printf("Final_LI: %i\n", final_LI);
// Suspect you want to convert 64-binary digit string to a 64-bit integer
// maybe by somehow using binary_decimal - suggest re-write of that function
unsigned long long LI_rcv_i = strtoull(LI_rcv_b, NULL, 2);
printf("Final_LI: %llu\n", LI_rcv_i);
free(ptr_record);
return 0;
}
Output
LI: 11111111111111111111111111111111
Final_LI: 4294967295
I have this code to get from binary to decimal:
#include <stdio.h>
#include <math.h>
#include <stdint.h>
int main() {
printf("%lld\n", binaryToDecimal(11110000111100001111000011110000));
return 1;
}
long long binaryToDecimal(long long binary) {
int power = 0;
return binaryToDecimalHelper(binary, power);
}
long long binaryToDecimalHelper(long long binary, int power) {
if (binary != 0) {
long long i = binary % (double)10;
return (i * pow(2, power))
+ binaryToDecimalHelper(binary / 10, power + 1);
} else {
return 0;
}
}
It works fine for small values (up to 16 bits) , but for 32 bits (which is what I need) it just returns garbage.
The number 11110000111100001111000011110000 is of type int, which can't hold a number as big as 11110000111100001111000011110000 in your machine. It's better to use a string representation instead ("11110000111100001111000011110000") and adjust your algorithm, if you can.
if you are limited to 32 bits maximum this is one example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void setStr(char *c, const char * x)
{
int i = 0;
while(x[i] != '\0')
{
c[i] = x[i];
i++;
}
}
void prepend(char* s, const char* t)
{
size_t len = strlen(t);
size_t i;
memmove(s + len, s, strlen(s) + 1);
for (i = 0; i < len; ++i)
{
s[i] = t[i];
}
}
int main(int argc, char const *argv[])
{
char *x = malloc(33*sizeof(char));
setStr(x, "111");
while (strlen(x) < 31) // not really necessary, but will help to 'cut' bytes if necessary
{
prepend(x,"0");
}
printf("%s\n", x);
int i = strtol(x,NULL,2);
printf("%d\n",i);
free(x);
return 0;
}
The first thing to be clear on is that your code does not convert anything to decimal, but rather to an int. Conversion to a decimal character string representation of that integer is performed by the printf() call.
The literal constant 11110000111100001111000011110000 is interpreted by the compiler (or would be if it were not so large) as a decimal value, and as such will require 104 bits to store;
i.e. log10(1111000011110000111100001111000010) / log10(210)
Representing a binary value with a decimal integer containing only 1 and 0 digits does not make much mathematical sense - though it may be convenient for small integers. A 64 bit unsigned long long is good for only 20 decimal digits (using just 1 and 0 - it can represent all 19 digit positive decimal integers, and some 20 digit values);
i.e. log10(210) * 6410
If you need longer binary values, then you should probably use a string representation. This is in fact simpler and more efficient in any case - you can use the fact that the machine representation of integers already is binary:
#include <stdio.h>
#include <stdint.h>
uint64_t binstrToInt( const char* binstr )
{
uint64_t result = 0 ;
int bit = 0;
while( binstr[bit] != '\0' )
{
if( binstr[bit] == '1' )
{
result |= 1 ;
}
bit++ ;
if( binstr[bit] != '\0' )
{
result <<= 1 ;
}
}
return result ;
}
int main()
{
printf("%llu\n", binstrToInt( "11110000111100001111000011110000" ) ) ;
return 0 ;
}
This would be easiest by far with a string as input instead of an int, and would allow longer numbers. Your problem is probably being caused by integer overflow.
String version:
#include <math.h>
#include <stdio.h>
#include <string.h>
int main() {
const char * const string_to_convert = "1010"
int result = 0;
for( int i = strlen(string_to_convert) - 1; i >= 0; --i ) {
if( string_to_convert[i] == '1' ) {
// Careful with pow() -- returns double, may round incorrectly
result += (int)pow( 10.0d, (double)i )
}
}
fprintf( stdout, "%d", result );
return 0;
}
Also, I'm not sure what the point of the return 1 is. Usually a non-zero return value from main indicates an error.
I have many different pseudo-random number generators written in C that generate an arbitrary number of pairs of random numbers (through the CLI) and store them in a (new) text file: a pair of numbers per column. I want to store 400.000.000 numbers in a text file, but when I look at the number of lines the file has, it has only 82.595.525 lines. This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "../Calculos/myfunctions.c"
void outputDevRandomOpenFile (FILE * from_file, FILE * to_file, unsigned long long how_many_pairs){
unsigned long long i = 0LL;
int seed;
unsigned long long max_period = 2147483648LL;
for (i = 0LL; i < how_many_pairs; i += 1LL){
fread (&seed, sizeof(int), 1, from_file);
fprintf (to_file, "%.10lf ", fabs (((double) seed) / ((double) max_period)));
fread (&seed, sizeof(int), 1, from_file);
fprintf (to_file, "%.10lf\n", fabs (((double) seed) / ((double) max_period)));
}
}
int main (int argc, char *argv[]){
char * endptr;
unsigned long long how_many_pairs = (unsigned long long) strtoull (argv[1], &endptr, 10);
FILE * urandom = fopen ("/dev/urandom", "r");
FILE * to_file = fopen ("generated_numbers_devrandom.txt", "w");
outputDevRandomOpenFile (urandom, to_file, how_many_pairs);
fclose (urandom);
return 0;
}
At first I suspected that there where some issue in the code (i.e. I could be choosing the wrong types of variables somewhere), but I tested it by including inside the for-loop a if (i > 165191050) printf ("%llu\n", i); (remind that I'm using a 1-D array for storing couples of numbers, not a 2-D one, so in the condition I just multiply 82595525*2) to test whether the problem was that the code was not looping 800.000.000 times, but only 165191050. When I performed the test, after i = 165191050, it just started to print out i values on the shell, so it really looped those 800.000.000 times, but when I looked the number of lines of the generated text file, there were 82595525 lines again. So I'm betting the problem is not in the code (or at least not in the types of variables I used).
I'm also getting the same results with this algorithm (this is just another different pseudo-random number generator):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MT_LEN 624
int mt_index;
unsigned long mt_buffer[MT_LEN];
void mt_init() {
int i;
for (i = 0; i < MT_LEN; i++)
mt_buffer[i] = rand();
mt_index = 0;
}
#define MT_IA 397
#define MT_IB (MT_LEN - MT_IA)
#define UPPER_MASK 0x80000000
#define LOWER_MASK 0x7FFFFFFF
#define MATRIX_A 0x9908B0DF
#define TWIST(b,i,j) ((b)[i] & UPPER_MASK) | ((b)[j] & LOWER_MASK)
#define MAGIC(s) (((s)&1)*MATRIX_A)
unsigned long mt_random() {
unsigned long * b = mt_buffer;
int idx = mt_index;
unsigned long s;
int i;
if (idx == MT_LEN*sizeof(unsigned long))
{
idx = 0;
i = 0;
for (; i < MT_IB; i++) {
s = TWIST(b, i, i+1);
b[i] = b[i + MT_IA] ^ (s >> 1) ^ MAGIC(s);
}
for (; i < MT_LEN-1; i++) {
s = TWIST(b, i, i+1);
b[i] = b[i - MT_IB] ^ (s >> 1) ^ MAGIC(s);
}
s = TWIST(b, MT_LEN-1, 0);
b[MT_LEN-1] = b[MT_IA-1] ^ (s >> 1) ^ MAGIC(s);
}
mt_index = idx + sizeof(unsigned long);
return *(unsigned long *)((unsigned char *)b + idx);
/* Here there is a commented out block in MB's original program */
}
int main (int argc, char *argv[]){
char * endptr;
const unsigned long long how_many_pairs = (unsigned long long) strtoll (argv[1], &endptr, 10);
unsigned long long i = 0;
FILE * file = fopen ("generated_numbers_mt.txt", "w");
mt_init ();
for (i = 0LL; i < how_many_pairs; i++){
fprintf (file, "%.10lf ", ((double) mt_random () / (double) 4294967295));
fprintf (file, "%.10lf\n", ((double) mt_random () / (double) 4294967295));
}
fclose (file);
return 0;
}
Again, it loops 800.000.000 times, but it only stores 165191050 numbers.
$ ./devrandom 400000000
$ nl generated_numbers_devrandom.txt | tail # Here I'm just asking the shell to number the lines of the text file and to print out the 10 last ones.
82595516 0.8182168589 0.0370640513
82595517 0.1133005517 0.8237414290
82595518 0.9035788113 0.6030153367
82595519 0.9192735264 0.0945496135
82595520 0.0542484536 0.7224835437
82595521 0.1827865853 0.9254508596
82595522 0.0249044443 0.1234162976
82595523 0.0371284033 0.8898798078
82595524 0.5977596357 0.9672102989
82595525 0.5523654688 0.29032228
What is going on here?
Thanks in advance.
Each line is 26 characters long, 82595525 lines x 26 = 2147483650 bytes
If you look closer to the file created, I'm quite sure the last line is truncated and the file size is precisely 2147483647, i.e. 2^31-1.
The reason why you can't write a larger file is either due to a file system limitation but more likely due to the fact you compile a (non large file aware) 32 bit binary, with which a file can't be more than 2147483647 as it is the largest signed integer that can be used.
If that is the case and if your OS is 64 bit, the simplest fix is to set the proper compiler flags to build a 64 bit binary which won't have this limitation.
Otherwise, have a look to abasterfield workaround.
Compile with CFLAGS -D_FILE_OFFSET_BITS=64 or put
#define _FILE_OFFSET_BITS 64
in your code before you include any libc headers