NO

Author Topic: Problem with opcode  (Read 6706 times)

leandrojardim

  • Guest
Problem with opcode
« on: October 14, 2012, 12:18:13 AM »
Hi, I have this code in my byte-based interpreter/virtual machine:

Code: [Select]
#define EXCEPTION_STACK_LENGTH 8
#define REGISTER_COUNT 16
#define MEMORY_CAPACITY 65536
#define ACCESS_VIOLATION 4
#define UNKNOWN_ERROR 8

#define REGISTER_PC (REGISTER_COUNT - 4)
#define REGISTER_SP (REGISTER_COUNT - 3)
#define REGISTER_FP (REGISTER_COUNT - 2)
#define REGISTER_ST (REGISTER_COUNT - 1)

// ----

typedef int WORD32;
typedef unsigned int UWORD32;

typedef unsigned short UWORD16;
typedef short WORD16;

typedef unsigned char BYTE8;
typedef char CHAR8;

// ----

typedef void (*PF_EXCEPTION_CALLBACK) (void *Object);

// ----

BYTE8 Memory[MEMORY_CAPACITY];
UWORD16 Register[REGISTER_COUNT];

UWORD32 Instruction;

// ----

UWORD16 Exception;
jmp_buf ExceptionStack[EXCEPTION_STACK_LENGTH];
UWORD32 ExceptionStackTop;

// ----

void ThrowException(WORD32 Code)
{
if (ExceptionStackTop == 0)
return;

Exception = Code;
longjmp(ExceptionStack[--ExceptionStackTop], 1);
};

WORD32 HandleException(PF_EXCEPTION_CALLBACK Function, void *Data)
{
if (ExceptionStackTop >= EXCEPTION_STACK_LENGTH) {
return UNKNOWN_ERROR;
};

if (setjmp(ExceptionStack[ExceptionStackTop++]) == 0) {
Function(Data);
ExceptionStackTop--;
return SUCCESS;
};

ExceptionStackTop--;
return Exception;
};

void CheckMemoryAddress(UWORD32 Address)
{
if (Address >= MEMORY_CAPACITY)
ThrowException(ACCESS_VIOLATION);
};

void CheckRegisterIndex(BYTE8 Index)
{
if (Index >= REGISTER_COUNT)
ThrowException(ACCESS_VIOLATION);
};

void CheckProgramCounter(UWORD32 Amount)
{
CheckMemoryAddress(Register[REGISTER_PC] + (Amount));
};

// ----

UWORD32 SwapWord32Order (UWORD32 Word) {
UWORD32 TemporaryData = 0;

TemporaryData = ((Word & 0xFF) << 24) | ((Word & 0xFF00) << 8);
TemporaryData = TemporaryData | ((Word & 0x00FF0000) >> 8) | ((Word & 0xFF000000) >> 24);

return TemporaryData;
};

void DecodeInstruction(void)
{
CheckProgramCounter(sizeof(UWORD32));
Instruction = 0;
Instruction = *(UWORD32*) &Memory[Register[REGISTER_PC]];
Instruction = SwapWord32Order(Instruction);
IncrementRegister (REGISTER_PC, sizeof (UWORD32));
};

void IncrementRegister (BYTE Index, UWORD16 Amount) {
CheckRegisterIndex(Index);
Register[Index] += Amount;
};

And a binary data-file created with the Pelles C hex-editor that contains these bytes in the order shown, and is read by the virtual machine until now (note that the virtual machine is of 16 bits, and its a big endian kind and the instructions are 32 bit):

Code: [Select]
0x01
0x00
0x00
0x05
0x02
0xC0
0x00
0x00
0x01
0x00
0x7C
0x08
0x02
0xC1
0x00
0x00
0x08
0x10
0x00
0x00
0x03
0xC0
0x00
0x0F
0x00
0x00
0x00
0x00

Well, for some reason when the interpreter decodes the data-file instruction 0000C102 (when the function DecodeInstruction reads the fourth dword of the data-file), it understands it as 027C0800 and not as 02C10000. Unfortunately, I could not see whats wrong with it, other opcodes work perfectly.  For some reason some mixing happens with the bytes near to the instruction, maybe an alignment fault of me. :(

I would need the help of somebody to understand what I have done wrong, please. :)
« Last Edit: October 14, 2012, 06:15:30 AM by leandrojardim »

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Problem with opcode
« Reply #1 on: October 14, 2012, 08:45:52 AM »
considering that 0x08 and 0x7C are the bytes just preceding the 4th DWord in question, I can only assume that you have an error in your reading loop.

In general, I don't think it is impossible to say for sure unless you show us some real code that is handling the input data when the error occurs as you describe...

Ralf

leandrojardim

  • Guest
Re: Problem with opcode
« Reply #2 on: October 15, 2012, 12:17:24 AM »
considering that 0x08 and 0x7C are the bytes just preceding the 4th DWord in question, I can only assume that you have an error in your reading loop.

In general, I don't think it is impossible to say for sure unless you show us some real code that is handling the input data when the error occurs as you describe...

Ralf

Hmm. At the point of decoding 0x0000C102, the PC is located at 0xC, so is the 12th byte and its exactly at the right point for decoding the instruction (I used the debugger to see it in action). This means all other opcodes advance the PC correctly. So the bug must be at the function DecodeInstruction or in any of these. For some reason in that instruction the pointer is fetching the backward dword! I never had this problem before and could not find any explanation for such behavior. :(
« Last Edit: October 15, 2012, 02:41:36 AM by leandrojardim »

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Problem with opcode
« Reply #3 on: October 15, 2012, 06:16:40 PM »
considering that 0x08 and 0x7C are the bytes just preceding the 4th DWord in question, I can only assume that you have an error in your reading loop.

In general, I don't think it is impossible to say for sure unless you show us some real code that is handling the input data when the error occurs as you describe...

Ralf
Hmm. At the point of decoding 0x0000C102, the PC is located at 0xC, so is the 12th byte and its exactly at the right point for decoding the instruction (I used the debugger to see it in action). This means all other opcodes advance the PC correctly. So the bug must be at the function DecodeInstruction or in any of these. For some reason in that instruction the pointer is fetching the backward dword! I never had this problem before and could not find any explanation for such behavior. :(
Ok, to fix my previous typing error, and rephrase: It is impossible to say what is wrong unless to show us some real code that is handling the input data..."

Ralf

leandrojardim

  • Guest
Re: Problem with opcode
« Reply #4 on: October 16, 2012, 02:16:58 AM »
Here it is. I modified it a bit for posting, basically the opcode changed to 0x11010000, but the side-effect is the same. :(
« Last Edit: October 16, 2012, 02:19:15 AM by leandrojardim »

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Problem with opcode
« Reply #5 on: October 16, 2012, 07:02:01 AM »
Sorry, didn't see that you had posted more code in the first post, I claim side effects from the pain killer I had used to treat the effects of a kidney infection I was dealing for the last 10 days.
I will take a closer look at this either later, or more likely early tomorrow morning (PDT)...

Ralf

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2091
Re: Problem with opcode
« Reply #6 on: October 16, 2012, 12:27:00 PM »
Code: [Select]
#include <stdio.h>

#define EXCEPTION_STACK_LENGTH 8
#define REGISTER_COUNT 16
#define MEMORY_CAPACITY 65536
#define ACCESS_VIOLATION 4
#define UNKNOWN_ERROR 8

#define REGISTER_PC (REGISTER_COUNT - 4)
#define REGISTER_SP (REGISTER_COUNT - 3)
#define REGISTER_FP (REGISTER_COUNT - 2)
#define REGISTER_ST (REGISTER_COUNT - 1)

typedef int WORD32;
typedef unsigned int UWORD32;

typedef unsigned short UWORD16;
typedef short WORD16;

typedef unsigned char BYTE8;
typedef char CHAR8;

BYTE8 Memory[] = {
0x01,0x00,0x00,0x05,
0x02,0xC0,0x00,0x00,
0x01,0x00,0x7C,0x08,
0x02,0xC1,0x00,0x00,
0x08,0x10,0x00,0x00,
0x03,0xC0,0x00,0x0F,
0x00,0x00,0x00,0x00
};

UWORD16 Register[REGISTER_COUNT];
UWORD32 Instruction;

void ThrowException(WORD32 Code)
{
}

void CheckMemoryAddress(UWORD32 Address)
{
if (Address >= MEMORY_CAPACITY)
ThrowException(ACCESS_VIOLATION);
};

void CheckRegisterIndex(BYTE8 Index)
{
if (Index >= REGISTER_COUNT)
ThrowException(ACCESS_VIOLATION);
};

void CheckProgramCounter(UWORD32 Amount)
{
CheckMemoryAddress(Register[REGISTER_PC] + (Amount));
};

// ----

UWORD32 SwapWord32Order (UWORD32 Word) {
UWORD32 TemporaryData = 0;

TemporaryData = ((Word & 0xFF) << 24) | ((Word & 0xFF00) << 8);
TemporaryData = TemporaryData | ((Word & 0x00FF0000) >> 8) | ((Word & 0xFF000000) >> 24);

return TemporaryData;
};

void IncrementRegister (BYTE8 Index, UWORD16 Amount) {
CheckRegisterIndex(Index);
Register[Index] += Amount;
};

void DecodeInstruction(void)
{
CheckProgramCounter(sizeof(UWORD32));
Instruction = 0;
Instruction = *(UWORD32*) &Memory[Register[REGISTER_PC]];
Instruction = SwapWord32Order(Instruction);
printf("%08X\n", Instruction);
IncrementRegister (REGISTER_PC, sizeof (UWORD32));
};

int main(int argc, char **argv)
{
int cnt = sizeof(Memory)/sizeof(UWORD32);
for (int i = 0; i < cnt; i++)
DecodeInstruction();
return 0;
}
prints
Code: [Select]
01000005
02C00000
01007C08
02C10000
08100000
03C0000F
00000000
May the source be with you

leandrojardim

  • Guest
Re: Problem with opcode
« Reply #7 on: October 18, 2012, 02:34:17 PM »
Thank you, I found the bug. I was addressing the emulated heap with a register index instead with a heap offset... :)