How to access PE NT headers from DOS headers? - c++

I'm trying to read a .exe PE file into memory and access NT headers. I can already access DOS headers but can't resolve NT headers from it.
Here's what I have so far:
static constexpr uint16_t DOS_HDR_MAGIC = 0x5A4D; // "MZ"
static constexpr uint32_t NT_HDR_MAGIC = 0x00004550; // "PE\x0\x0"
struct nt_headers_t
{
uint32_t signature;
file_header_t file_header;
optional_header_x64_t optional_header;
};
struct dos_header_t
{
uint16_t e_magic;
uint16_t e_cblp;
uint16_t e_cp;
uint16_t e_crlc;
uint16_t e_cparhdr;
uint16_t e_minalloc;
uint16_t e_maxalloc;
uint16_t e_ss;
uint16_t e_sp;
uint16_t e_csum;
uint16_t e_ip;
uint16_t e_cs;
uint16_t e_lfarlc;
uint16_t e_ovno;
uint16_t e_res[ 4 ];
uint16_t e_oemid;
uint16_t e_oeminfo;
uint16_t e_res2[ 10 ];
uint32_t e_lfanew;
};
int main(void) {
std::ifstream input("./stuff.exe", std::ios::in | std::ios::binary );
input.seekg(0, std::ios::end);
int file_size = input.tellg();
input.seekg(0, std::ios::beg);
std::byte *file = new std::byte[file_size];
input.read((char *)file, file_size);
struct dos_header_t *dos_header = (struct dos_header_t *)file;
assert(dos_header->e_magic == DOS_HDR_MAGIC);
struct nt_headers_t *nt_headers = (struct nt_headers_t *)file + dos_header->e_lfanew;
assert(nt_headers->signature == NT_HDR_MAGIC);
}
e_lfanew should contain address to the start of NT headers. I simply add this value to file start: (struct nt_headers_t *)file + dos_header->e_lfanew;
Am I doing that wrong? Attached picture says that e_lfanew contains the NT headers offset in reverse order. How should I reverse it?

I simply add this value to file start: (struct nt_headers_t *)file + dos_header->e_lfanew;
Am I doing that wrong?
Yes, but for a "boring reason" that has nothing to do with PE headers: since you've done the cast before the addition, the offset is scaled by the size of nt_headers_t. The offset needs to be added unscaled, so add it first, and cast afterwards.
Attached picture says that e_lfanew contains the NT headers offset in reverse order. How should I reverse it?
It's in little-endian byte order, you're probably running the code on a little-endian machine (that's most of them nowadays) so you don't need to do anything, just reading the value will interpret it correctly.

Related

ESP32 build in Arduino IDE: undefined reference to `CLASS::function' error

I tried to write an Library for the Sensirion SFM3000 Flow Sensor in the Arduino IDE for an ESP32. As long as it was one sketch, everything worked. But as I tried to seperate it into an .h and .cpp file and implemented it as a class, I get some weird error when I try to compile the sketch.
sketch\SFM3019_HSKA.cpp.o:(.literal._ZN12SFM3019_HSKA17i2c_read_flow_CRCEv+0x4): undefined reference to `SFM3019_HSKA::crc8(unsigned char, unsigned char)'
sketch\SFM3019_HSKA.cpp.o: In function `SFM3019_HSKA::i2c_read_flow_CRC()':
sketch/SFM3019_HSKA.cpp:124: undefined reference to `SFM3019_HSKA::crc8(unsigned char, unsigned char)'
sketch/SFM3019_HSKA.cpp:128: undefined reference to `SFM3019_HSKA::crc8(unsigned char, unsigned char)'
collect2.exe: error: ld returned 1 exit status
exit status 1
Fehler beim Kompilieren für das Board ESP32 Dev Module.
As I understand the error message, it occurs when the i2c_read_flow_CRC() meethod is calling the crc8() method in the last thrid of SFM3019_HSKA.cpp file. By now I don´t see an error in the syntax. But I have also no other idea on how to continue debugging...
This is the main code im trying to use the library in:
#include "SFM3019_HSKA.h"
#include <Wire.h>
SFM3019_HSKA::SensVal_s SensVal = {0, 0, 0};
SFM3019_HSKA SFM3019(0x2E); //Generate Object SFM3019 of class SFM3019_HSKA
void setup() {
// put your setup code here, to run once:
Serial.begin (115200);
delay(100);
Wire.begin (21, 22); // for ESP32: SDA= GPIO_21 /SCL= GPIO_22
SFM3019.i2c_device_check(); //checks if I2C device is available
SFM3019.i2c_write(0x3608); //write 2Byte to start continuous measurement
delay(100);
}
void loop() {
// put your main code here, to run repeatedly:
SensVal.flow = SFM3019.i2c_read_flow_CRC(); //read only Flow Bytes
Serial.println(SensVal.flow, 10);
delay(100);
SensVal = SFM3019.i2c_read_all(); //read all Sensor Bytes
Serial.print("Flow: ");
if (SensVal.flow >= 0) Serial.print(" "); //just for beauty reasons
Serial.print(SensVal.flow,10);
Serial.print(" Temp: ");
Serial.print(SensVal.temp,3);
Serial.print(" Statusword: ");
Serial.print(SensVal.statusword, HEX);
delay(400);
Serial.println();
}
and those are the library files:
SFM3019_HSKA.h
#ifndef SFM3019_HSKA_H // include guard
#define SFM3019_HSKA_H
#include "Arduino.h"
class SFM3019_HSKA {
public: //can be accessed public
SFM3019_HSKA(uint8_t i2cAddress); //Constructor
//may be nicer in private if it works anyway
typedef struct {float flow; float temp; int16_t statusword;} SensVal_s; //Struct for complete Sensor Readout
SensVal_s SensVal = {0, 0, 0}; //initialize with 0
int8_t i2c_device_check(); //function for Initialisation
int8_t i2c_write(const uint16_t SendData); //function to write 16Bit Data to sensor
SensVal_s i2c_read_all(); //function to read Flow, Temperature and Statusword
float i2c_read_flow(); //function to only read Flow
float i2c_read_flow_CRC(); //function to only read Flow with CRC check
private: //can only be accessed by functions oh same object
uint8_t SFM3019addr = 46; //SFM3019 I2C Adress: 46 / 0x2E
uint8_t crc8(const uint8_t data, uint8_t crc); //fuction for CRC confirmation
};
#endif
and the C++ file leading to the error:
SFM3019_HSKA.cpp:
#include "SFM3019_HSKA.h" //when placed in same folder
//#include <SFM3019_HSKA.h> //when placed in standard library folder
#include <Wire.h>
// some values needed for calculation of physical flow and temperature values
#define SFM3019Offset 24576
#define SFM3019ScaleFactorFlow 170.0 //needs to be a float, otherwise it will not calculate in float
#define SFM3019ScaleFactorTemp 200.0 //needs to be a float, otherwise it will not calculate in float
SFM3019_HSKA::SFM3019_HSKA(uint8_t i2cAddress) //constructor
{
//: mI2cAddress(i2cAddress)
SFM3019addr = i2cAddress;
}
/* checks if a Device at the desired address is responding with an ACK */
int8_t SFM3019_HSKA::i2c_device_check(){
Wire.beginTransmission(SFM3019addr); // Begin I2C transmission Address (i)
if (Wire.endTransmission() == 0) // Receive 0 = success (ACK response)
{
Serial.print ("Found Seosor at address");
Serial.print (SFM3019addr, DEC);
Serial.print (" (0x");
Serial.print (SFM3019addr, HEX); // 7 bit address
Serial.println (")");
return 0; //0=device sent ACK
}else{
Serial.print ("Did not receive Acknowledge from I2C address ");
Serial.print (SFM3019addr, DEC);
Serial.print (" (0x");
Serial.print (SFM3019addr, HEX); // 7 bit address
Serial.println (")");
return 1; //no ACK received
}
}
/* writes a 16bit "SendData" to I2C Bus Device "address" */
int8_t SFM3019_HSKA::i2c_write(const uint16_t SendData) {
Wire.beginTransmission(SFM3019addr);
//fill I2C outbuffer
Wire.write((SendData>>8)& 0xFF); //isolate HighByte
Wire.write(SendData & 0xFF); //isolate LowByte
//send I2C outbuffer
Wire.endTransmission();
return 0;
}
/* reads all 9 measurement bytes for flow, temp and status */
SFM3019_HSKA::SensVal_s SFM3019_HSKA::i2c_read_all(){
SensVal_s SensVal = {0}; //create empty struct
Wire.requestFrom(SFM3019addr, 9, true); // Request 9byte (3x16bit + CRC) from the sensor
//while(Wire.available()<3){}; //wait for all the data to be received //ATTENTION may be critical loop forever, however not using this may lead to an error, as the Buffer may be processed faster, then the input is read on I2C
//get Flow Bytes
int16_t flow = Wire.read()<<8; //get Highbyte and shift 8bit to 8MSB
flow = flow | Wire.read(); //get Lowbyte 8LSB
byte CRCflow = Wire.read(); //get CRC Check Byte (you could do a data validy check with that)
//Serial.println(flow, HEX); //raw values for debugging
SensVal.flow = (flow + SFM3019Offset) / SFM3019ScaleFactorFlow; //calculate the flow in slm as Datasheet mentions
//get Temperature Bytes
int16_t temp = Wire.read()<<8; //get Highbyte and shift 8bit to 8MSB
temp = temp | Wire.read(); //get Lowbyte 8LSB
byte CRCtemp = Wire.read(); //get CRC Check Byte (you could do a data validy check with that)
//Serial.println(temp, HEX); //raw values for debugging
SensVal.temp = temp / SFM3019ScaleFactorTemp; //calculate the flow in slm as Datasheet mentions
//get StatusWord Bytes
int16_t stat = Wire.read()<<8; //get Highbyte and shift 8bit to 8MSB
stat = stat | Wire.read(); //get Lowbyte 8LSB
byte CRCstat = Wire.read(); //get CRC Check Byte (you could do a data validy check with that)
//Serial.println(stat, HEX); //raw values for debugging
SensVal.statusword = temp / SFM3019ScaleFactorTemp; //calculate the flow in slm as Datasheet mentions
//return all data
return SensVal;
}
/* reads only first 3 bytes for flow and does NO CRC!*/
float SFM3019_HSKA::i2c_read_flow(){
Wire.requestFrom(SFM3019addr, 3, true); // Request 9byte (2x16bit + CRC) from the sensor
//while(Wire.available()<3){}; //wait for all the data to be received //ATTENTION may be critical loop forever, however not using this may lead to an error, as the Buffer may be processed faster, then the input is read on I2C
int16_t flow = Wire.read()<<8; //get Highbyte and shift 8bit to 8MSB
flow = flow | Wire.read(); //get Lowbyte 8LSB
byte CRC = Wire.read(); //get CRC Check Byte (you could do a data validy check with that)
//Serial.println(flow, HEX); //raw values for debugging
return (flow + SFM3019Offset) / SFM3019ScaleFactorFlow; //calculate the flow in slm as Datasheet mentions
}
/* reads only first 3 bytes for flow and DOES CRC*/
float SFM3019_HSKA::i2c_read_flow_CRC(){
Wire.requestFrom(SFM3019addr, 3, true); // Request 9byte (2x16bit + CRC) from the sensor
//while(Wire.available()<3){}; //wait for all the data to be received //ATTENTION may be critical loop forever, however not using this may lead to an error, as the Buffer may be processed faster, then the input is read on I2C
uint8_t Highbyte = Wire.read(); //get Highbyte 8MSB
uint8_t Lowbyte = Wire.read(); //get Lowbyte 8LSB
uint8_t CRC = Wire.read(); //get CRC Check Byte
//Confirm CRC
uint8_t mycrc = 0xFF; // initialize crc variable
mycrc = crc8(Highbyte, mycrc); // let first byte through CRC calculation
mycrc = crc8(Lowbyte, mycrc); // and the second byte too
if (mycrc != CRC) { // check if the calculated and the received CRC byte matches
//Serial.println("Error: wrong CRC");
return -10000; //extreme low value, so user knows somethig is wrong
} else {
//Serial.println("Success: identical CRC");
int16_t flow = (Highbyte<<8) | Lowbyte; //stack the to bytes together as signed int16
return (flow + SFM3019Offset) / SFM3019ScaleFactorFlow; //calculate the flow in slm as Datasheet mentions
}
}
/* calculate a CRC Byte, (Cyclic Redundancy Check) */
uint8_t crc8(const uint8_t data, uint8_t crc)
{
crc ^= data; //crc XOR data
for ( uint8_t i = 8; i; --i ) {
crc = ( crc & 0x80 )
? (crc << 1) ^ 0x31
: (crc << 1);
}
return crc;
}
I would be really thankfull for any idea on how to continue...
/* calculate a CRC Byte, (Cyclic Redundancy Check) */
uint8_t crc8(const uint8_t data, uint8_t crc)
{
crc ^= data; //crc XOR data
for ( uint8_t i = 8; i; --i ) {
crc = ( crc & 0x80 )
? (crc << 1) ^ 0x31
: (crc << 1);
}
return crc;
}
Needs to be:
/* calculate a CRC Byte, (Cyclic Redundancy Check) */
uint8_t SFM3019_HSKA::crc8(const uint8_t data, uint8_t crc)
{
crc ^= data; //crc XOR data
for ( uint8_t i = 8; i; --i ) {
crc = ( crc & 0x80 )
? (crc << 1) ^ 0x31
: (crc << 1);
}
return crc;
}
You just forgot to mark the defined method as part of the class. Simple typo error.

Populating struct resembling an IP Header with nibbles/sub-8-bit values

I've been wanting to get into networking with raw sockets recently and have decided to perform a generic ICMP ping using C++ and raw sockets.
I started with making a struct called IP_Header, defined as such:
struct IP_Header {
uint8_t version : 4;
uint8_t IHL : 4;
uint8_t DSCP : 6;
uint8_t ECN : 2;
uint16_t total_len;
uint16_t ident;
uint16_t flags : 3;
uint16_t frag_offset : 13;
uint8_t ttl;
uint8_t proto;
uint16_t header_chksum;
uint32_t src;
uint32_t dst;
};
And so i populated this struct with some default values:
void populateHeaderDefault(IP_Header* ip) {
ip->version = 4;
ip->IHL = 5;
ip->DSCP = 0;
ip->ECN = 0;
ip->total_len = htons(20); //header only
ip->ident = htons(1);
ip->flags = 2;
ip->frag_offset = 0;
ip->ttl = 64;
ip->proto = IPPROTO::IPPROTO_HOPOPTS;
ip->header_chksum = 0;
IN_ADDR ia;
inet_pton(AF_INET, "192.168.178.31", &ia);
ip->src = ia.S_un.S_addr;
inet_pton(AF_INET, "127.0.0.1", &ia);
ip->dst = ia.S_un.S_addr;
ip->header_chksum = header_checksum(ip, sizeof IP_Header);
}
However, the resulting IP Header Version/IHL contains 0x54 instead of 0x45, and the short that contains the Flags and Fragmentation is 0x0200 instead 0f 0x4000. (I'm comparing my values to an exact copy of the packet recreated in scapy)
So my question is how I would fix these values? I know manually assigning the right value would probably work, but I'd like to use nibbles for better accessability.
So my question is how I would fix these values?
The values in the struct are already correct. The problem is in how you use the value. You simply cannot rely on order of bit fields.
Here is a correct way to get 0x45 from the Version/IHL:
uint8_t verIHL = ip->version << 4 | ip->IHL;
You can declare version and header length bitfields based on host machine byte order similar to Linux IP header as shown below, which will make sure right values set.
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
Secondly, you can define IP flags supported and set required values as below,
#define IP_FLAG_RF 0x8000 /* reserved fragment flag */
#define IP_FLAG_DF 0x4000 /* dont fragment flag */
#define IP_FLAG_MF 0x2000 /* more fragments flag */
ip->flags = htons(IP_FLAG_DF);

Why can't I read registers through SPI on STM32?

I'm trying to connect a LSM6DSOX sensor board with SPI to the Nucleo-STM32L011K4. It looks like I can succesfully read to the board, and I use the following code for it:
static int32_t platform_write(void *handle, uint8_t reg, uint8_t *bufp,
uint16_t len)
{
HAL_GPIO_WritePin(GPIOA, CS_Pin, GPIO_PIN_RESET);
BSP_SPI1_Send(&reg, 1);
BSP_SPI1_Send(bufp, len);
HAL_GPIO_WritePin(GPIOA, CS_Pin, GPIO_PIN_SET);
return 0;
}
However, when I try to read from a single register, like the WHO_AM_I register, I always get back 0x00 (which should not be the case). I use the following code for reading:
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,
uint16_t len)
{
reg |= 0x80;
HAL_GPIO_WritePin(GPIOA , CS_Pin, GPIO_PIN_RESET);
BSP_SPI1_Send(&reg, 1);
BSP_SPI1_Recv(bufp, len);
HAL_GPIO_WritePin(GPIOB, CS_Pin, GPIO_PIN_SET);
return 0;
}
I can not figure out why this does not work. I thought many other code-parts were the problem, but I think I narrowed it down to this part. Anyone can spot an error?
You need to enable register address increment.
See datasheet for LSM6DSOX. In register CTRL3_C(12h) set she bit IF_INC.

Boost Asio accessing asio::ip::address underlying data and byte ordering

My goal is to create a unique ID for all IP address - port pair. The UID must be same across systems (no conflict for different endian systems). Size of IPV4 UID is 6 bytes and for ipv6 is 18 bytes.
uint8_t sourcePair[18]; /*ipv4=(4+2) bytes or ipv6=(16+2) bytes*/
I have two functions that will take the remote endpoint of a socket and get the desired UID. The design is as follows.
void CmdInterpreter::makeSourcePairV4(asio::ip::tcp::endpoint& remoteEp, unsigned short portNum, unsigned char(&binSourcePair)[18])
{
auto addressClass = remoteEp.address().to_v4();
auto ipBin = addressClass.to_uint();
memcpy(&binSourcePair[0], &ipBin, 4);
memcpy(&binSourcePair[4], &portNum, 2);
}
void CmdInterpreter::makeSourcePairV6(asio::ip::tcp::endpoint& remoteEp, unsigned short portNum, unsigned char(&binSourcePair)[18])
{
auto addressClass = remoteEp.address().to_v6();
auto ipBin = addressClass.to_bytes();
memcpy(&binSourcePair[0], &ipBin[0], 16);
memcpy(&binSourcePair[16], &portNum, 2);
}
This is how these functions are called
remoteEp = socketPtr->remote_endpoint();
if (remoteEp.address().is_v4())
CmdInterpreter::makeSourcePairV4(remoteEp, remoteEp.port(), sourcePair);
else
CmdInterpreter::makeSourcePairV6(remoteEp, remoteEp.port(), sourcePair);
Here the problem is the only way to access the IPv6 underlying data is using to_byte() which will give the data in network byte order. Also, I am doing a memcopy in unsigned short which is multibyte in length. Does this work? Is it a safe way? Is their any workarounds?
void CmdInterpreter::makeSourcePairV4(asio::ip::tcp::endpoint& remoteEp, unsigned short portNum, uint8_t(&sourcePair)[18])
{
auto addressClass = remoteEp.address().to_v4();
auto ipBin = addressClass.to_bytes();
memcpy(&sourcePair[0], &ipBin[0], 4);
#ifdef BOOST_ENDIAN_LITTLE_BYTE
byteSwap(portNum);
#endif
memcpy(&sourcePair[4], &portNum, 2);
}
void CmdInterpreter::makeSourcePairV6(asio::ip::tcp::endpoint& remoteEp, unsigned short portNum, uint8_t(&sourcePair)[18])
{
auto addressClass = remoteEp.address().to_v6();
auto ipBin = addressClass.to_bytes();
memcpy(&sourcePair[0], &ipBin[0], 16);
#ifdef BOOST_ENDIAN_LITTLE_BYTE
byteSwap(portNum);
#endif
memcpy(&sourcePair[16], &portNum, 2);
}
For both IPv4 and IPv6 address, use to_byte() function to get the remote endpoint address in big-endian format. For little-endian host, the port number will make endianness problem which can be fixed by swapping the bytes. To encode it to base 64 I used cppcodec library.
UID = cppcodec::base64_rfc4648::encode(sourcePair, 6);
UID = cppcodec::base64_rfc4648::encode(sourcePair, 18);
The template function used to swap the port number is:
template <typename T>
void byteSwap(T& portNumber)
{
char* startIndex = static_cast<char*>((void*)&portNumber);
char* endIndex = startIndex + sizeof(T);
std::reverse(startIndex, endIndex);
}

Bit fields keil hardfault after restarting

When I use this struct just after flashing device it works well, but after restarting (power on/off) using this struct(assign to any bit) cause a HardFault irq. I use Keil uVision with STM32F205. Why it not works? and what should I change/remove/add to fix it? Direct using GPIOC->ODR don't cause any problems what is wrong with bitfields in Kail?
#pragma anon_unions
typedef union {
struct {
__IO uint16_t Data_Bus:8; // 0-7 data bus
__IO uint16_t Ctr_Pins:6; // 8-13 control pins
__IO uint16_t :2; // 14-15 unused here
};
struct {
__IO uint16_t D0:1; // 0 data bus pin
__IO uint16_t D1:1; // 1 data bus pin
__IO uint16_t D2:1; // 2 data bus pin
__IO uint16_t D3:1; // 3 data bus pin
__IO uint16_t D4:1; // 4 data bus pin
__IO uint16_t D5:1; // 5 data bus pin
__IO uint16_t D6:1; // 6 data bus pin
__IO uint16_t D7:1; // 7 data bus pin
// --------------------------------
__IO uint16_t RS:1; // 8 reset
__IO uint16_t CS:1; // 9 chip select
__IO uint16_t CD:1; // 10 control / data
__IO uint16_t RD:1; // 11 read tick
__IO uint16_t WR:1; // 12 write tick
__IO uint16_t EN:1; // 13 enable display
// ---------------------------------
__IO uint16_t :1; // 14 unused
__IO uint16_t LD:1; // 15 led
};
} *PC_STRUCT_PTR, PC_STRUCT;
PC_STRUCT_PTR __TMP = (PC_STRUCT_PTR)(GPIOC_BASE+0x14);
#define PINOUTS (*__TMP)
it's used like this:
void Write_Reg(unsigned char command)
{
PINOUTS.CD = 0; PINOUTS.RD = 1; PINOUTS.CS = 0; PINOUTS.WR = 0;
PINOUTS.Data_Bus = command; wait();
PINOUTS.WR = 1; PINOUTS.CS = 1; PINOUTS.CD = 1; wait();
}
In file 'startup_stm32f20x.s', make sure that you have the following piece of code:
EXTERN HardFault_Handler_C ; this declaration is probably missing
__tx_vectors ; this declaration is probably there
DCD HardFault_Handler
Then, in the same file, add the following interrupt handler (where all other handlers are located):
PUBWEAK HardFault_Handler
SECTION .text:CODE:REORDER(1)
HardFault_Handler
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B HardFault_Handler_C
Then, in file 'stm32f2xx.c', add the following ISR:
void HardFault_Handler_C(unsigned int* hardfault_args)
{
printf("R0 = 0x%.8X\r\n",hardfault_args[0]);
printf("R1 = 0x%.8X\r\n",hardfault_args[1]);
printf("R2 = 0x%.8X\r\n",hardfault_args[2]);
printf("R3 = 0x%.8X\r\n",hardfault_args[3]);
printf("R12 = 0x%.8X\r\n",hardfault_args[4]);
printf("LR = 0x%.8X\r\n",hardfault_args[5]);
printf("PC = 0x%.8X\r\n",hardfault_args[6]);
printf("PSR = 0x%.8X\r\n",hardfault_args[7]);
printf("BFAR = 0x%.8X\r\n",*(unsigned int*)0xE000ED38);
printf("CFSR = 0x%.8X\r\n",*(unsigned int*)0xE000ED28);
printf("HFSR = 0x%.8X\r\n",*(unsigned int*)0xE000ED2C);
printf("DFSR = 0x%.8X\r\n",*(unsigned int*)0xE000ED30);
printf("AFSR = 0x%.8X\r\n",*(unsigned int*)0xE000ED3C);
printf("SHCSR = 0x%.8X\r\n",SCB->SHCSR);
while (1);
}
If you can't use printf at the point in the execution when this specific Hard-Fault interrupt occurs, then save all the above data in a global buffer instead, so you can view it after reaching the while (1).
Then, refer to the 'Cortex-M Fault Exceptions and Registers' section at http://www.keil.com/appnotes/files/apnt209.pdf in order to understand the problem, or publish the output here if you want further assistance.