GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 20-Apr-2008, 01:54
aijazbaig1's Avatar
aijazbaig1 aijazbaig1 is offline
Member
 
Join Date: May 2006
Location: Sweden
Posts: 122
aijazbaig1 will become famous soon enough
Lightbulb

seg fault on ptr to ptr assignment!


Hello,

I am faced with a weird issue which I do not know how to approach. I have a function which multiplies two 64bit ints using 32bit wide chunks. The algorithm is pretty simple and we just have to shift and add the partial products. And I have managed to write a function which does just that.

But Im facing seg fault issues within the function which I assume is mostly due to referring illegal memory. BUt I do not seem to find out why exactly is that...

The program is as shown below. I have put a comment above the first line which gives me a seg fault. The header file libepc.h contains the definitions for DWORD32 and QWORD64 which are nothing but unsigned long and unsigned long long on an x86 respectively. I have it because I plan to use some other routines from that header file in order to communicate with a machine without an operating system.

CPP / C++ / C Code:
#include "libepc.h"
#include <stdlib.h>
#include "string.h"
#include <stdio.h>

void llmultiply(QWORD64 , QWORD64 , unsigned char *);//function signature, definition below
unsigned char res[16];//array of 16 chars (128 bits) to store the result of the multiplciation, used in the function llmultiply

int main()

//     QWORD64 L1,L2;
//     unsigned char* res;

{
    QWORD64 L1,L2;
    //unsigned char* res;

    L1 = 0x12FF353C2323FF29;
    L2 = 0x5A2F12AF1234DF54;
  
    //call routine with the needed args, compiler takes care of passing params and ret val
    llmultiply(L1,L2,res);

    puts("the result is");
    puts(res);
    return 0;
}

void llmultiply(QWORD64 mlp,QWORD64 mlr, unsigned char* result)

     /*function llmultiply multiplies 2 64 bit ints and stores the result at the location pointed to by result*/
     //mlr - Multiplier, mlp - multiplicand

     //extern unsigned char res[16];//array to store the 128 bit wide result     
{
    register DWORD32 upper_mlr,upper_mlp;//containers to store the upper words of mlr and mlp 
    register DWORD32 lower_mlr,lower_mlp;//containers to store the upper words of mlr and mlp

    register QWORD64 *pp_lower0_ptr,*pp_lower1_ptr;//pointers to containers to store the partial products generated by the lower word of mlr
    register QWORD64 *pp_upper0_ptr,*pp_upper1_ptr;//pointers to containers to store the partial products generated by the upper word of mlr
     
    register DWORD32 *tmp_32;
    QWORD64 tmp_64;

    upper_mlr = ((mlr & 0xFFFFFFFF00000000)>>32);//extracting upper dword32 of multiplier
    lower_mlr = ((mlr & 0x00000000FFFFFFFF));//extracting lower dword32 of multiplier

    upper_mlp = ((mlp & 0xFFFFFFFF00000000)>>32);//extracting upper dword32 of multiplicand
    lower_mlp = ((mlp & 0x00000000FFFFFFFF));//extracting lower dword32 of multiplicand

    /*now we do the actual 32bit multiplications.we need to cast only ONE of the operands to QWORD64 so that the result is indeed cast to 64 bit without being truncated as can be read from here: [url]www.fefe.de/intof.html[/url] */

    tmp_64 = (QWORD64)lower_mlr*lower_mlp;//generate partial product 0
    
   //THE LINE BELOW FLAGS A SEG FAULT 
    pp_lower0_ptr = &tmp_64;
    
    //    *pp_lower0_ptr = (QWORD64)lower_mlr*lower_mlp;//generate partial product 0
    *pp_lower1_ptr = (QWORD64)lower_mlr*upper_mlp;//generate partial product 1

    *pp_upper0_ptr = (QWORD64)upper_mlr*lower_mlp;//generate partial product 2
    *pp_upper1_ptr = (QWORD64)upper_mlr*upper_mlp;//generate partial product 3

    //now we reuse the 32 bit wide register variables above as we have the partial product safely stored

    lower_mlr = ((*pp_lower0_ptr & 0xFFFFFFFF00000000) >> 32);//lower_mlr now contains upper 32 bits from pp_lower0
    upper_mlr = ((*pp_upper1_ptr & 0x00000000FFFFFFFF)); //upper_mlr now contains lower 32 bits from pp_upper1

    //*tmp_32 = lower_mlr + (DWORD32)*pp_lower1_ptr + (DWORD32)*pp_upper0_ptr;

    //*tmp_32 = lower_mlr + *((DWORD32)pp_lower1_ptr) + *((DWORD32)pp_upper0_ptr);
    *tmp_32 = lower_mlr + *(pp_lower1_ptr) + *(pp_upper0_ptr);

    memmove(result,pp_lower0_ptr,4);//store the lowermost DWORD
    memmove(result+4,tmp_32,4);//store the next DWORD 4 bytes from start

    *tmp_32 = upper_mlr + *((char*)pp_lower1_ptr + 4) + *((char*)pp_upper0_ptr + 4);
    memmove(result+8,tmp_32,4);//store the next DWORD 8 bytes from start

    memmove(result+12,((char*)pp_upper1_ptr + 4),4);//store final DWORD 12 bytes from start

    result[16] = '/0';
    //result = res;//make result point to this contiguous mem location
}
I would be greatly obliged if someone would give me some hints about what is causing the seg. fault. What I have experimented with is that when I remove the keyword 'register', that is the variables are no more register variables then that line doesn't seg. fault anymore. Furthermore, if thats the way to solve this issue the I'd need a hell lot of temporary storage for all the intermediate results like these. Is there an intelligent way to do this. One way would be to use 'global variables' but I have heard that over dependence on globals is not a very good idea. But since I am kind of short here with the stack space, I have to find more better ways to utilize the available stack space. Do you guys have better suggestions?

You do not need to know any assembly for that I guess ..im keen to know what you have to say!!
__________________
Hope to hear from you guys!

--------------------------------------------------

Best Regards,
Aijaz Baig.
  #2  
Old 20-Apr-2008, 08:42
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,620
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: seg fault on ptr to ptr assignment!


Quote:
Originally Posted by aijazbaig1
...I am faced with a weird issue which I do not know how to approach...


CPP / C++ / C Code:
    *pp_lower1_ptr = (QWORD64)lower_mlr*upper_mlp;
What is the value of pp_lower1_ptr at this point?
You have other places where you store things using an uninitialized pointer.
Also...

I won't even try to understand the code or your approach. I mean, if I really studied it, I might ask why the heck you are using all of those pointers in the first place. If the compiler you are using supports 64-bit operations, then why not just store the 64-bit values with assignment statements (Maybe have variables named upper_upper, upper_lower, lower_upper, and lower_lower or some such things to hold the partial products.)


Also, I note the following:

You allocate an array of 16 unsigned chars:
CPP / C++ / C Code:
unsigned char res[16];

Then, with this array as the argument in calling the function
CPP / C++ / C Code:
    llmultiply(L1,L2,res);
.
.
.
void llmultiply(QWORD64 mlp,QWORD64 mlr, unsigned char* result)
.
.
.
    result[16] = '/0';
.
.
.

There are two things wrong:

1. You are storing something beyond the end of the array.

2. I think you mean to store zero, but that is an invalid character constant. (Didn't your compiler give a warning? My GNU compiler complained with the message "large integer implicitly truncated to unsigned type".) If other parts of your program depend on having a zero in whatever position you store it, it probably won't find it. (My GNU compiler gives a value of 0x30 there, but the actual result is undefined.)

If you want to store zero in that character position, you can use something like
CPP / C++ / C Code:
    x = '\0';
Or, simply
CPP / C++ / C Code:
    x = 0;

However, it's kind of silly to store a zero byte here anyhow. The result will be in the 16 chars of the array. Some of the bytes in the result may be zero. There is absolutely no reason to put a zero byte at the end, even if you had room for it.

This leads up to my last observation:

FInally: Your result will be some binary values stored in your char array. You certainly can't expect puts() to print the value of the result, since puts() prints chars corresponding to each element of the array.
Quote:
Originally Posted by aijazbaig1
..better suggestions...

First suggestion: Get it to work on your workstation. Then look at ways of getting it to fit into your target. Sometimes we use globals because of hardware considerations that limit the amount of stack space. (After all, in assembly-language programs everything is a global, even temporary variables used in different subroutines. You do what you have to do.) Also, declaring something a "register' variable should have absolutely no effect on any workstation compiler, so seg-faulting with or without "register" declarations is coincidental. Getting the target compiler or cross-compiler to use "register" variables is very implementation-dependent, and my recent experiences have shown time and time again that when I try to "help" the compiler make the "right" decision it doesn't help (and, sometimes actually hurts).


Regards,

Dave

"Functionality first; optimization later."
---davekw7x
  #3  
Old 21-Apr-2008, 04:30
aijazbaig1's Avatar
aijazbaig1 aijazbaig1 is offline
Member
 
Join Date: May 2006
Location: Sweden
Posts: 122
aijazbaig1 will become famous soon enough

Re: seg fault on ptr to ptr assignment!


hello,
Quote:
I won't even try to understand the code or your approach. I mean, if I really studied it, I might ask why the heck you are using all of those pointers in the first place. If the compiler you are using supports 64-bit operations, then why not just store the 64-bit values with assignment statements (Maybe have variables named upper_upper, upper_lower, lower_upper, and lower_lower or some such things to hold the partial products.)
The function llmultiply has been rewritten as shown below.
CPP / C++ / C Code:
void llmultiply(QWORD64 mlp,QWORD64 mlr, unsigned char* result)

     /*function llmultiply multiplies 2 64 bit ints and stores the result at the location pointed to by result*/
     //mlr - Multiplier, mlp - multiplicand

     //extern unsigned char res[16];//array to store the 128 bit wide result     
{
    DWORD32 upper_mlr,upper_mlp;//containers to store the upper words of mlr and mlp 
    DWORD32 lower_mlr,lower_mlp;//containers to store the upper words of mlr and mlp

    QWORD64 pp_lower0,pp_lower1;//pointers to containers to store the partial products generated by the lower word of mlr
    QWORD64 pp_upper0,pp_upper1;//pointers to containers to store the partial products generated by the upper word of mlr
     
    DWORD32 tmp_32_lower,tmp_32_upper;
    //QWORD64 tmp_64;

    upper_mlr = ((mlr & 0xFFFFFFFF00000000)>>32);//extracting upper dword32 of multiplier
    lower_mlr = ((mlr & 0x00000000FFFFFFFF));//extracting lower dword32 of multiplier

    upper_mlp = ((mlp & 0xFFFFFFFF00000000)>>32);//extracting upper dword32 of multiplicand
    lower_mlp = ((mlp & 0x00000000FFFFFFFF));//extracting lower dword32 of multiplicand

    /*now we do the actual 32bit multiplications.we need to cast only ONE of the operands to QWORD64 so that the result is indeed cast to 64 bit without being truncated as can be read from here: [url]www.fefe.de/intof.html[/url] */

    //tmp_64 = (QWORD64)lower_mlr*lower_mlp;//generate partial product 0
    pp_lower0 = (QWORD64)lower_mlr*lower_mlp;
    //    *pp_lower0_ptr = (QWORD64)lower_mlr*lower_mlp;//generate partial product 0
    pp_lower1 = (QWORD64)lower_mlr*upper_mlp;//generate partial product 1

    pp_upper0 = (QWORD64)upper_mlr*lower_mlp;//generate partial product 2
    pp_upper1 = (QWORD64)upper_mlr*upper_mlp;//generate partial product 3

    //now we reuse the 32 bit wide register variables above as we have the partial product safely stored

    lower_mlr = ((pp_lower0 & 0xFFFFFFFF00000000) >> 32);//lower_mlr now contains upper 32 bits from pp_lower0
    upper_mlr = ((pp_upper1 & 0x00000000FFFFFFFF)); //upper_mlr now contains lower 32 bits from pp_upper1

    //*tmp_32 = lower_mlr + (DWORD32)*pp_lower1_ptr + (DWORD32)*pp_upper0_ptr;

    //*tmp_32 = lower_mlr + *((DWORD32)pp_lower1_ptr) + *((DWORD32)pp_upper0_ptr);
    tmp_32_lower = lower_mlr + (DWORD32)*((char*)&pp_lower1) + (DWORD32)*((char*)&pp_upper0);//lower_middle partial product

    memmove(result,&pp_lower0,4);//store the lowermost DWORD
    memmove(result+4,&tmp_32_lower,4);//store the next DWORD 4 bytes from start

    tmp_32_upper = upper_mlr + (DWORD32)*((char*)&pp_lower1 + 4) + (DWORD32)*((char*)&pp_upper0 + 4);
    memmove(result+8,&tmp_32_upper,4);//store the next DWORD 8 bytes from start

    memmove(result+12,((char*)&pp_upper1 + 4),4);//store final DWORD 12 bytes from start
}
In this, I have this expression:
CPP / C++ / C Code:
tmp_32_lower = lower_mlr + (DWORD32)*((char*)&pp_lower1) + (DWORD32)*((char*)&pp_upper0);//lower_middle partial product
. If I change this line to look:
CPP / C++ / C Code:
tmp_32_lower = lower_mlr + (DWORD32)pp_lower1 + (DWORD32)pp_upper0;//lower_middle partial product
Then tmp_32_lower turns up to be 64bits using gdb!!..now thats really strange isn't it?..

Then I have used an expression like the following in the code:
CPP / C++ / C Code:
tmp_32_upper = upper_mlr + (DWORD32)*((char*)&pp_lower1 + 4) + (DWORD32)*((char*)&pp_upper0 + 4);

I wanted to add upper_mlr(32bits) to the upper 32bits of pp_lower1(64bits) and pp_upper0(64bits). I do this by casting their addresses as char* and then increase the addresses by 4 chars, so I get the upper 32 bits. I wonder if its ok to do that!..but it works for me though

And again, as Im using gdb to try to find my way through the code, I see some interesting things. When I print tmp_32_lower using gdb, it gives me '0x027fc9f5' and when i use memmove to copy this to the next 4 bytes of 'result' using
CPP / C++ / C Code:
memmove(result+4,&tmp_32_lower,4);
, the values gets zeroed out. So in gdb the instruction 'x (result+4)' gives me a value of all zeroes at 'result+4'. Its the same for all subsequent 32bit wide chunks from 'result+8' to 'result+12' . Why is the copy not happening in the latter cases as it did with 'result+0'?

I hope i haven't messed up my question too much...but I can frame it more clearly if you guys say so..

Keen to hear from you guys!
__________________
Hope to hear from you guys!

--------------------------------------------------

Best Regards,
Aijaz Baig.
Last edited by aijazbaig1 : 21-Apr-2008 at 05:06.
  #4  
Old 21-Apr-2008, 09:49
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,620
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: seg fault on ptr to ptr assignment!


Quote:
Originally Posted by aijazbaig1
The function llmultiply has been rewritten
It's somewhat easier to read without all of those pointers. (No seg faults, either, right?)

Quote:
Originally Posted by aijazbaig1
...tmp_32_lower turns up to be 64bits using gdb!!..now thats really strange isn't it?...

gdb is a tool. Not all tools are perfect. Since we can't look over your shoulder and see exactly what you see, it's pretty hard for me personally to see how to help with gdb and with the interpretation of its output.

Sometimes using tools like gdb can help give you some insight. With other people's code, I sometimes use gdb when the code confuses me.


Does your code give you what you expect to get? Did you try something like:
CPP / C++ / C Code:
    printf("tmp_32_lower = 0x%08x\n", tmp_32_lower);
    {int i;
        printf("Printing four bytes, starting at result+4\n");
        for (i = 0; i < 4; i++) {
            printf("%02x ", result[4+i]);
        }
        printf("\n");
    }
What did it say? Maybe something like:
Code:
tmp_32_lower = 0x027fc99f Printing four bytes, starting at result+4 9f c9 7f 02

In other words, when gdb confuses me, I look at the code and make the program tell me exactly what it is seeing.

By the way, using memmove the way that you did to copy lower and upper parts of the variables means that it only works with little-endian systems. If your target system is little-endian, then it will work the same way as on your little-endian workstation, but not all embedded system processors are little-endian. (Intel X-scale, for example, only works as a big-endian machine with their distribution code.) Just thought I would mention it.

Also, you didn't ask, but I observe that there is a bug in your function that gives errors for certain large input values.

For example If you change L1 and L2 both to be 0xffffffffffffffff (That's 64 bits of all ones), you get
Code:
0xffffffffffffffff * 0xffffffffffffffff = 0xfffffffefffffffd0000000000000001

Whereas, the correct value is given by
Code:
0xffffffffffffffff * 0xffffffffffffffff = 0xfffffffffffffffe000000000000000

Regards,

Dave
  #5  
Old 21-Apr-2008, 12:33
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,620
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: seg fault on ptr to ptr assignment!


Quote:
Originally Posted by davekw7x
Whereas, the correct value is given by
Code:
0xffffffffffffffff * 0xffffffffffffffff = 0xfffffffffffffffe000000000000000 <---Wrong! Should have '1' at the end

Oh, no! I made an error pasting that in there. I had the right value on my screen, but my hand slipped when copying to the post. I really, really hate it when that happens.

Here's the correct value:

Code:
0xffffffffffffffff * 0xffffffffffffffff = 0xfffffffffffffffe0000000000000001

That is: 15 'f' and an 'e', then 15 '0' and a '1'


I regret the error.


Regards,

Dave

Footnote:
You don't even need a computer for multiplications like this:

If I use '^' to indicate "to the power"
Code:
(2^n - 1) * (2^n - 1) = 2^(2n) - 2^(n+1) + 1
Now write out the bits for various values of n:
Code:
4 bits: (0x0000000000000000000f)^2 = 0xe1 8 bits: (0x000000000000000000ff)^2 = 0xfe01 12 bits: (0x00000000000000000fff)^2 = 0xffe001 16 bits: (0x0000000000000000ffff)^2 = 0xfffe0001 20 bits: (0x000000000000000fffff)^2 = 0xffffe00001 24 bits: (0x00000000000000ffffff)^2 = 0xfffffe000001 28 bits: (0x0000000000000fffffff)^2 = 0xffffffe0000001 32 bits: (0x000000000000ffffffff)^2 = 0xfffffffe00000001 36 bits: (0x00000000000fffffffff)^2 = 0xffffffffe000000001 40 bits: (0x0000000000ffffffffff)^2 = 0xfffffffffe0000000001 44 bits: (0x000000000fffffffffff)^2 = 0xffffffffffe00000000001 48 bits: (0x00000000ffffffffffff)^2 = 0xfffffffffffe000000000001 52 bits: (0x0000000fffffffffffff)^2 = 0xffffffffffffe0000000000001 56 bits: (0x000000ffffffffffffff)^2 = 0xfffffffffffffe00000000000001 60 bits: (0x00000fffffffffffffff)^2 = 0xffffffffffffffe000000000000001 64 bits: (0x0000ffffffffffffffff)^2 = 0xfffffffffffffffe0000000000000001 68 bits: (0x000fffffffffffffffff)^2 = 0xffffffffffffffffe00000000000000001 72 bits: (0x00ffffffffffffffffff)^2 = 0xfffffffffffffffffe000000000000000001 76 bits: (0x0fffffffffffffffffff)^2 = 0xffffffffffffffffffe0000000000000000001 80 bits: (0xffffffffffffffffffff)^2 = 0xfffffffffffffffffffe00000000000000000001
  #6  
Old 30-Apr-2008, 03:03
aijazbaig1's Avatar
aijazbaig1 aijazbaig1 is offline
Member
 
Join Date: May 2006
Location: Sweden
Posts: 122
aijazbaig1 will become famous soon enough

Re: seg fault on ptr to ptr assignment!


Hi everybody,
After taking a break, im back at them labs in school. Well, luckily I regrouped and now after a through rethinking of the whole problem, I was finally able to get this assignment done in Assembly.

On the contrary, the C version of this function gives the correct result for the operands 0xFFFFFFFFFFFFFFFF and 0xFFFFFFFFFFFFFFFF and I do see the 'E' in the correct place.

Now suprisingly it isn't working for the other test cases needed to complete this lab.
Looks like it is the way we display the result may be. The result has to be stored into an array of unsigned character. Hence we have to progress byte by byte and display the result.

Before I show the code,I would like to say that for some reason, my lab partner wanted to work with 64bit values directly instead of dividing it into 32bit wide chunks and to me that looked unneccesarily complicated. Nonetheless, it works for the first test case and it doesn't work for the others as it gives drastically different results.

Heres the C code:
CPP / C++ / C Code:
#include "libepc.h"

void llmultiply(unsigned long long int l1, unsigned long long int l2, unsigned char *result);

void llmultiply_C(unsigned long long int l1, unsigned long long int l2, unsigned char *result){
	unsigned long int Alow;
	unsigned long int Ahigh;
	unsigned long int Blow;
	unsigned long int Bhigh;
	unsigned long long int r1;
	unsigned long long int r2;
	unsigned long long int r3;
	unsigned long long int r4;
	unsigned long long int temp;
	int cnt = 1;
	int i ;
	
	
	Alow = l1 ;
	Ahigh = (l1 >>32);
	Blow = l2;
	Bhigh = (l2>>32);
	
	printf("Ahigh  is %ulX\n", Ahigh);
        printf("Alow  is %ulX\n", Alow);
        //	SetCursorPosition(cnt++, 0);
	
	
        printf("Bhigh  is %ulX\n", Bhigh);
        printf("Blow  is %ulX\n", Blow);
        //	SetCursorPosition(cnt++, 0);
		
	//A high * B high
	r1 = (unsigned long long int)Ahigh * Bhigh;	
	//A high * B low
	r2 = (unsigned long long int)Ahigh * Blow;
	//A low * B high
	r3 = (unsigned long long int)Alow * Bhigh;
	//A low * B low
	r4 = (unsigned long long int)Alow * Blow;
	//r4 = Alow * Blow;
	
        //	SetCursorPosition(cnt++, 0);

        //	PutString("\n\rAlow * Blow is: ");
	printf("Alow * Blow  is %ullX\n", r4);
        //	SetCursorPosition(cnt++, 0);
	
	temp = r2;
	r2 = r2 + r3;
	if((r2 < temp) || (r2 < r3))r1 += 0x100000000;
	
        //	PutString("\n\r r2 = r2 + r3  is: ");
	printf("r2 = r2 + r3  is %ullX\n", r2);
        //	SetCursorPosition(cnt++, 0);
	
	temp = r4;
	
        //	PutString("\n\r r4 beefore addition is: ");
	printf("r4 before addition  is %ullX\n", r4);
        //	SetCursorPosition(cnt++, 0);	

	r4 = r4 + (r2<<32);		
	if((r4 < temp) || (r4 < (r2<<32)))
	{
		r2 += 0x100000000;
		
	}
        //	SetCursorPosition(cnt++, 0);
        //       	PutString("\n\rr4 after addition is: ");
	printf("r4 after addition  is %ullX\n", r4);
	
	temp = r2;
	r2 += (r1<<32); 
	if((r2 < temp) || (r2 < (r1<<32)))
	{
		r1 += 0x100000000;
	}	
	
	
	
	for(i=0; i<8;i++){
		result[i] = r4>>(i*2);
	}
	
	for(i=8; i<12;i++){
		result[i] = r2>>(32 + (i-8)*2);
	}
	
	for(i=12; i<16;i++){
		result[i] = r1>>(32 + (i-12)*2);
	}
	
	
}
int main(int argc, char *argv[]) {
	unsigned long long int l1;
	unsigned long long int l2;
	unsigned char result[16];
	int i ;
	
	//ClearScreen(0x07);
	//SetCursorPosition(0, 0);
			
	l1 = 0x111122223333 ;
	l2 = 0x555566667777 ;
	
	llmultiply_C(l1, l2, result);
        //	PutString("\n\rThe Result is: ");
	puts("the result is:");
	for (i=15; i>=0;i--){
		//printf("      is %*(result + i) , 16 , 2);
		//printf("      is %result[i]  , 16 , 2);	
            putchar(result[i]);
	}
	/*SetCursorPosition(15, 0);
	llmultiply(l1, l2, result); 
	
	PutString("\n\rThe Result is: ");
	for (i=15; i>=0;i--){
		printf("      is %*(result + i) , 16 , 2);	
                }	*/
			
	return 0;
}

The header file needed for this is here:
CPP / C++ / C Code:
/* ============================================================ */
/* File: LIBEPC.H						*/
/*								*/
/* Copyright (C) 2001, Daniel W. Lewis and Prentice-Hall	*/
/*								*/
/* Purpose: Various #defines, structures, and function		*/
/* prototypes needed to use the corresponding library LIBEPC.A.	*/
/*								*/
/* Designed for use with the DJGPP port of the GNU C/C++	*/
/* protected mode 386 compiler.					*/
/*								*/
/* Modification History:					*/
/*								*/
/* ============================================================ */

#ifndef _LIBEPC_H_	/* Avoid multiple inclusions */
#define	_LIBEPC_H_

/* ------------------------------------------------------------ */
/* A few datatypes to make the operand size more obvious.	*/
/* ------------------------------------------------------------ */
typedef int			BOOL	;
typedef unsigned char		BYTE8	;
typedef unsigned short int	WORD16	;
typedef unsigned long int	DWORD32	;
typedef unsigned long long int	QWORD64	;
typedef signed long int		FIXED32	;       /* 16.16 Fixed-Point */
typedef signed long long int	FIXED64	;       /* 32.32 Fixed-Point */
typedef void			(*ISR)(void) ;	/* Pointer to an ISR */

/* ------------------------------------------------------------ */
/* Constants for use with datatype BOOL (above).		*/
/* ------------------------------------------------------------ */
#ifndef TRUE
#define	TRUE		1
#endif
#ifndef FALSE
#define	FALSE		0
#endif

/* ------------------------------------------------------------ */
/* Macros to extract the LSByte and MSByte of a WORD16 value	*/
/* ------------------------------------------------------------ */
#define	LSB(u)		((u) & 0xFF)
#define	MSB(u)		((u) >> 8)

/* ------------------------------------------------------------ */
/* Returns number of elements in an array. (Use in for loops.)	*/
/* ------------------------------------------------------------ */
#define	ENTRIES(a)	(sizeof(a)/sizeof(a[0]))

/* ------------------------------------------------------------ */
/* Declaration prefix to hide an object from the linker.	*/
/* ------------------------------------------------------------ */
#define	PRIVATE		static

/* ------------------------------------------------------------ */
/* Define a NULL pointer.					*/
/* ------------------------------------------------------------ */
#ifndef NULL
#define	NULL		((void *) 0)
#endif

/* ------------------------------------------------------------ */
/* 386 instructions needed when writing ISR's.	Note that IRET	*/
/* pops the pointer to the stack frame that was established by	*/
/* code that the compiler generates at every function entry.	*/
/* ------------------------------------------------------------ */
#define	PUSHCS		__asm__ __volatile__ ("PUSHL %CS") ;
#define	PUSHF		__asm__ __volatile__ ("PUSHFL")
#define	POPF		__asm__ __volatile__ ("POPFL")
#define	STI		__asm__ __volatile__ ("STI")
#define	CLI		__asm__ __volatile__ ("CLI")
#define	PUSHA		__asm__ __volatile__ ("PUSHAL")
#define	POPA		__asm__ __volatile__ ("POPAL")
#define	ENTER		__asm__ __volatile__ ("ENTER $0,$0")
#define	LEAVE		__asm__ __volatile__ ("LEAVE")
#define	IRET		__asm__ __volatile__ ("IRET")

/* ------------------------------------------------------------ */
/* Support for functions implemented in IO.ASM			*/
/* ------------------------------------------------------------ */
void		outportb(WORD16, BYTE8) ;
BYTE8		inportb(WORD16) ;
void		exit(int) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in INIT-CRT.C		*/
/* ------------------------------------------------------------ */
void *		LastMemoryAddress(void) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in INIT-IDT.C		*/
/* ------------------------------------------------------------ */
#define		IRQ_TICK	0
#define		IRQ_KYBD	1
#define		IRQ_COM2_COM4	3
#define		IRQ_COM1_COM3	4
#define		IRQ_FLOPPY	6
#define		IRQ_PAR_PORT	7
#define		IRQ_RTC		8
#define		IRQ_PS2_MOUSE	12
#define		IRQ_HARD_DISK	14

int		IRQ2INT(int irq) ;
ISR		GetISR(int int_numb) ;
void		SetISR(int int_numb, ISR isr) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in KEYBOARD.C		*/
/* ------------------------------------------------------------ */
BYTE8		GetScanCode(void) ;
BOOL		ScanCodeRdy(void) ;
BOOL		SetsKybdState(BYTE8) ;
WORD16		ScanCode2Ascii(BYTE8 code) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in SPEAKER.C		*/
/* ------------------------------------------------------------ */
void		Sound(int hertz) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in CYCLES.ASM		*/
/* ------------------------------------------------------------ */
QWORD64		CPU_Clock_Cycles(void) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in TIMER.C			*/
/* ------------------------------------------------------------ */
DWORD32		Milliseconds(void) ;
DWORD32		Now_Plus(int seconds) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in DISPLAY.C		*/
/* ------------------------------------------------------------ */
WORD16 *	Cell(int row, int col) ;
void		ClearScreen(BYTE8 attb) ;
char *		FormatUnsigned
		(char *bfr, unsigned val, int base, int width, char fill) ;
int		GetCursorCol(void) ;
int		GetCursorRow(void) ;
void		PutAttb(BYTE8 attb, int cells) ;
void		PutChar(char ch) ;
void		PutCharAt(char ch, int row, int col) ;
void		PutString(char *string) ;
void		PutUnsigned(unsigned val, int base, int width) ;
void		SetCursorPosition(int row, int col) ;
void		SetCursorVisible(BOOL visible) ;
char *		Unsigned2Ascii(char *bfr, unsigned val, int base) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in WINDOW.C		*/
/* ------------------------------------------------------------ */
typedef struct ROWCOL
	{
	int	first ;
	int	last ;
	int	cursor ;
	} ROWCOL ;

typedef struct WINDOW
	{
	ROWCOL	row ;
	ROWCOL	col ;
	char	title[1] ;
	} WINDOW ;

WINDOW *	WindowCreate(char *title, int row_first, int row_last,
			int col_first, int col_last) ;
void		WindowErase(WINDOW *w) ;
void		WindowPutChar(WINDOW *w, char ch) ;
void		WindowPutString(WINDOW *w, char *str) ;
void		WindowSelect(WINDOW *w) ;
void		WindowSetCursor(WINDOW *w, int row, int col) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in HEAP.C			*/
/* ------------------------------------------------------------ */
void *		malloc(long unsigned int) ;
void		free(void *) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in QUEUE.C			*/
/* ------------------------------------------------------------ */
typedef	struct QUEUE
	{
	int	item_size ;
	int	max_items ;
	int	item_count ;
	int	nq_index ;
	int	dq_index ;
	char	bfr[0] ;
	} QUEUE ;

QUEUE *		QueueCreate(int numb_items, int item_size) ;
BOOL		QueueInsert(QUEUE *q, void *data) ;
BOOL		QueueRemove(QUEUE *q, void *data) ;

/* ------------------------------------------------------------ */
/* Support for functions implemented in FIXEDPT.ASM		*/
/* ------------------------------------------------------------ */
#define FIXED32_ONE		65536L
#define FIXED32_PI		205887L
#define FIXED32_2PI		411775L
#define FIXED32_E		178144L
#define FIXED32_ROOT2		74804L
#define FIXED32_ROOT3		113512L
#define FIXED32_GOLDEN		106039L

#define FLOAT32(x)		((FIXED32) ((x) << 16))
#define TRUNC32(x)		((int) ((x) >> 16))
#define ROUND32(x)		((int) (((x) + 0x8000) >> 16))

FIXED32		Product32(FIXED32 multiplier, FIXED32 multiplicand) ;
FIXED32		Quotient32(FIXED32 dividend, FIXED32 divisor) ;
FIXED32		Inverse32(FIXED32 n) ;
FIXED32		Sqrt32(FIXED32 n) ;
FIXED64		Product64(FIXED64 multiplier, FIXED64 multiplicand) ;

#endif
I have replaced various display functions needed for the embedded device with the generic printfs and put statements so that you guys can see the output if u wish.
However in actuality Im supposed to use the ones for the embedded device and I have commented them out so they can still be seen.
I hope to get some insights into why my program doesn't work for the other seemingly simpler inpputs but it seems to work for the corner case which dave also pointed out in his previous post.
__________________
Hope to hear from you guys!

--------------------------------------------------

Best Regards,
Aijaz Baig.
  #7  
Old 30-Apr-2008, 08:31
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,620
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: seg fault on ptr to ptr assignment!


Quote:
Originally Posted by aijazbaig1
On the contrary, the C version of this function gives the correct result for the operands 0xFFFFFFFFFFFFFFFF and 0xFFFFFFFFFFFFFFFF and I do see the 'E' in the correct place.
The function that you posted previously gave the answer that I posted previously.
Quote:
Originally Posted by aijazbaig1
...it isn't working for the other test cases
I guess you are saying that you changed the function to give you what you were looking for with one test case, but it's wrong for other test cases.

So, it's incorrect and you have to debug it. I mean, when you get seg faults it is sometimes hard proceed. But when the program runs to completion and you get output and it's wrong, then you can track it down.

You have put a few print statements in place. Use them.

First of all, I like to make the print statements actually print something in a meaningful format so that I can use the output to see where things went wrong.

For example, take the test case in this post:
CPP / C++ / C Code:
    printf("Ahigh is 0x%08lX\n", Ahigh);
    printf("Alow  is 0x%08lX\n", Alow);
    //      SetCursorPosition(cnt++, 0);


    printf("Bhigh is 0x%08lX\n", Bhigh);
    printf("Blow  is 0x%08lX\n", Blow);
    //      SetCursorPosition(cnt++, 0);
    r4 = (unsigned long long int) Alow *Blow;
    //r4 = Alow * Blow;

    //      SetCursorPosition(cnt++, 0);

    //      PutString("\n\rAlow * Blow is: ");
    printf("Alow * Blow  is 0x%llX\n", r4);

This much of the code gives
Code:
Ahigh is 0x00001111 Alow is 0x22223333 Bhigh is 0x00005555 Blow is 0x66667777 Alow * Blow is 0xDA749F47C0481B5

Now one thing for sure: if it is done correctly, then none of the other cross products can affect the lower 32 bits of this, right? Now sneak a peak the correct answer given for this problem: the 32 least significant bits are 0x7C0481B5, which agrees with the 32 least significant bits of the printed value. So up to this part it's OK.

Now fix the print statement in your main() function so that it actually prints the output array from the function, and you will see something like
Code:
the result is: 00000000871D76D912482081061B6DB5
Now, you can see that something in your function (after Alow*Blow was calculated) screwed up the lower bits, which shouldn't have been touched.

If you have any specific questions about what you don't understand about what you see, then ask, but I won't go any further in trying to unravel the stuff in your function; it's your problem, not mine. Just take it a step at a time.

Regards,

Dave
  #8  
Old 30-Apr-2008, 11:32
aijazbaig1's Avatar
aijazbaig1 aijazbaig1 is offline
Member
 
Join Date: May 2006
Location: Sweden
Posts: 122
aijazbaig1 will become famous soon enough

Re: seg fault on ptr to ptr assignment!


Hello there,

thanks dave for giving me some solid examples. I was finally able to fix the code and what i was doing wrong was that I was not putting the correct values in the correct places i.e. the way i transferred stuff to 'result' was just so wrong...
anyway, heres the correct way in which I have done the transfer and it seems to work now:
CPP / C++ / C Code:
	for(i=1; i<=8;i++){
		result[(i-1)] = r4>>(i-1)*8;
	}
	
	for(i=1; i<=4;i++){
		result[(i-1)+8] = r2>>(32 + (i-1)*8);
	}
	
	for(i=1; i<=4;i++){
		result[(i-1)+12] = r1>>(32 + (i-1)*8);
	}
Now what I think was that the result of the very first multiplication was such that it may have permitted this wrongful transfer yet give the right result may be due to its combination of so many trailing zeros or whatever.

Well...this one works and im satisfied..thnks again
__________________
Hope to hear from you guys!

--------------------------------------------------

Best Regards,
Aijaz Baig.
 

Recent GIDBlogFirst week of IA training by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Assignment Operator and Pointer Peter_APIIT CPP / C++ Forum 14 25-Sep-2007 05:36
double concatenated dynamic list - different type assignment warning dlp C Programming Language 11 01-Jun-2007 07:59
Thread synchronization Assignment help!! rossi143 C Programming Language 1 25-Mar-2007 20:10
Am I reading this assignment correctly? earachefl CPP / C++ Forum 2 09-May-2006 09:39
Circular Linked Queue Copy Constructor and Assignment Operator Not Working? wc3promet CPP / C++ Forum 0 17-Oct-2004 07:55

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 16:01.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.