Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Rhinorhino on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Witting binary output... 1

Status
Not open for further replies.

jstreich

Programmer
Joined
Apr 20, 2002
Messages
1,067
Location
US
I'm working on a MIPS assembler and I need to write out opt codes (ints) as raw binary that is a set bit length (6 bits)... so.... How do I write it out... I know about the write() that takes a char* and a size, but even casting the int to a char array doesn't seem to work... Ideas?
 
Not enough info. Have you a problem with packing six-bits on byte (8-bit) binary stream? Add buffer class to accept code by code, pack them in native words or bytes and write on stream (attach(FILE* /* or fstream&*/), emit(int/*6 bit op code*/), flush(), close() member functions).
Or what else?
 
I suppose I was vauge...
I have supped up container class that has two linked lists, and a lookup tabel for labels to addresses. The linked list takes pointers to objects of types derived from a Node class. Each node derived class has a write that takes a stream (which I want to write the nodes value out in binary from)... For instance I have:

Code:
class TypeI : public Word
{
public:
  TypeI(int op, int s, int t, int i) : opt(op), rs(s), rt(t), imm(i){}
  virtual ~TypeI(){}
  virtual void write(ostream & sout);
  int opt;
  int rs;
  int rt;
  int imm;
  const static int optSize = 6; //number of bits for opt
  const static int rsSize = 5; //number of bits for rs
  const static int rtSize = 5; //number of bits for rt
  const static int immSize = 11;
};


So I need a clean way to do the binary output in the Type's write(). When using the ostream's write() on a binary stream to STDOUT, I was running into a odd numbers instead of weird chars (using a (char*) so the types match... I know that this should work (it works for longs in a Hex editor's code I was looking at). The harder stuff in the assembling came fairly easily, but how to write the darn thig out is dring me nuts. It is a 32 bit word, and 8 bit bytes, but the instructon format has to fit all the info into one word, so the opt and registers, ect. are truncated to a certian number of bits. The instructions are word aligned. I have been able to find little information on binary streams... using the old write() and the iso::binary don't seem to work the way they are promised. Any help would be apreciated.
 
I suppose you have 3 problems.
#1. Make binary output stream: ofstream f(file_name,ios::binary); or use f.open(fn,ios::binary).
#2. Pack bit fields (opcode etc) into the memory word: use shifts as unsigned w = (opt&0x3F); w |= (rs&0x1F)<<6; w |= (rt&0x1F)<<11; w |= (is&0x7FF)<<16;/* draw word and check my calculations, but see subproblem 2 below */. Use unsigned ints when work on bits level.
#3. Put this stuff onto the stream: use f.write((const char*)&word,4) instead of << op. Now we (you) have two subproblems. We put 4 bytes with 27 actual bits if the consumer can ignore idle trailer 5-bit gap. If not, we must buffer output to pack 27-bit chunks w/o any gaps. The 2nd: byte ordering in your target comp. My shifts work for Intel CPUs, where word_ptr->{byte0,byte1,byte2,byte3}. Don't search any docs if you have doubts, simply check it: write 0x03020100U (as above) onto the junk file and see result with hex ed.
Check cmd fields bit alignment specs once more, correct shift values if you need and go forward!
I may suggest any more decorations, but that's all now.
 
I found a cleaner way to do it. As it turns out, there is a way to control how large an int is declared:
int i:6;

So you can use a struct or class that is one word long and cast it as a char* to ostream's write().
 
Oopps. I will still need to shift bits...
 
jstreich, C/C++ bit fields in structures are too low-powered. No language standard assumptions about true alignment (mapping) in the underlying word. Honest and cumbersome shifts give us more controllable and clear solution.
I may, indeed, be wrong but struct bit field is illusory and useless language feature.
 
After looking into it, shifiting was the way to go. The bit feilds did indeed work to produce a binary output of the proper size and would allow me to read back in the data as an object of the same type -- however, the output was unexpected, I think the endianess was wrong and it was padded with an extra word of zeros.

The shifiting of the bits seems to take less then than a multiply (obviously) and gives proper output. So, although bit-feilds are neat, you are rightm they aren't useful.
 
The output error wasn't in the endianess, the data being passed to the object was wrong... meaning bit feilds would have worked... the bit shifting was just extra work... Just thought that I'd point that out. Bitfields would have been bad code if it had to be maintainable... no one would have a clue how it worked looking back at it...
 
In principal no difference between shifting or bit fields approaches (bit fields use shift instructions too). You may get ANY desired bit alignment in ANY machine words.
Binary streams work fine in any (I think) C/C++ implementations. On debug stage you may print out result byte stream (byte by byte) in hexa format then correct your shifts/ors appropriately.

And what is a problem? ...passed to the object was wrong? What is wrong? Why?
Do you know exact field alignment from technical specification? If not, have you correct examples of packed code?

No need to study language/compiler issues about bit shifting global problems. If you must pack some bits into some words (in right order) - you can - do it...

Or I know nothing about music...
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Sponsor

Back
Top