How to print a string in protected mode in c - operating-system

I am starter in os Deving and manage to make a bootloader and then a kernel.I cam successfully jumped to protected mode and transfer the control to kernel.I able to write single characters but printing string is not working.This is my printString() function.
void printString(char * message[]){
int i;
for(i = 0; message[i] != '\0'; i++)
{
print(message[i]);
}
}
And My print Character function is here
void print(char *character){
unsigned char *vidmem = (unsigned char *) VIDEO_ADDRESS;
int offset; //Variable which hold the offset where we want to print our character
offset = GetCursor(); //Setting our offset to current cursor position
vidmem[offset+1] = character;
vidmem[offset+2] = 0x0f;
SetCursor(offset+2);
}
and this is call to function
printString("manoj");
Please help me I am a starter in os deving

I would recommend keeping track of the X and Y coordinates as (static) globals, and using them for offsets into memory. Also, it shouldn't be offset+1 and offset+2, but rather offset and offset+1. This is in addition to what tangrs said in his answer.
A good tutorial for learning how to print to the screen can be found at http://www.jamesmolloy.co.uk/tutorial_html/3.-The%20Screen.html - he goes into great detail about how to print things. It also is a good place to start learning about OSDev, along with the OSDev forums at http://forum.osdev.org/index.php.

There's several things wrong with your functions
Firstly, your print function takes a pointer to a character where it looks like you want the character itself.
Secondly, your printString function is really taking a pointer to pointer to char which isn't what you want if you're calling the printString function like printString("Hello World");.
Your compiler should have warned you about these.
Your code should looks something like this
void printString(char * message){
// ...
}
void print(char character){
// ...
vidmem[offset+1] = character;
// ...
}

Related

error while taking input in c programming

[programming//in this code i am able only to enter one
value through scan F() FUNCTION although i have used loop up to 5 but when i enter first value program automatically ends whats wrong please answer???][1]
code:
#include<stdio.h>
#include<conio.h>
int main()
{
int arr[5];
int j=0;
if(j<5){
printf("enter\n");
scanf("%d",&arr[j]);
printf("well enter next");
int y;
y=arr[j];
if (y<5)
{ printf("value:%d",arr[j]);
}
j++;
}
return 0;
}
I think you need to figure this out on your own, but let me help you get started.
Let me show you how to store 5 integers taken from the keyboard and you'll have to learn the rest. C is a hard language to start with, so don't be discouraged, I'm still a beginner too.
I will also use some code formatting that I like. There are probably better formats out there but definitely think about how the code looks on the screen.
practice.c
#include<stdio.h>
int main() {
int arr[5];
int j=0;
printf("Enter the first integer:");
while (j<5) {
scanf("%d",&arr[j]);
printf("Next:");
j++;
}
/* I'd then practice printing out the 5 integers.
* Then you can figure out how to stop the loop based on some logical condition.
*/
return 0;
}
Compile with:
gcc -Wall -o practice practice.c

Emonlib+ADS1115+ESP32+Arduino Function Pointer

I have tried to contact the original designer for the ADS1115->EmonLib adaptation, but unfortunately his Github page has no contact information. I have also tried asking on the OpenEnergyMonitor forum and I get "Contact the person who made the changes".
So, I've come here in the hopes that the knowledgeable folk here can help me out.
Situation:
I have an ESP32 that I'm going to be using to monitor my energy consumption of my home. Because I will be monitoring several circuits I need lots of sensors. The ESP32 only has a 12-bit ADC and I'm limited to only a few sensors. Also limits future expansion if needed.
So here comes the ADS1115, which is a 16-bit ADC, but it uses I2C. Unfortunately, the EmonLib was designed to use onboard ADC, and not through an I2C device. So after doing some digging around, I found this modification to allow the ADS1115 to be used:
https://github.com/PaulWieland/EmonLib/
However, Paul Wieland is not able to be contacted through github.
Ok, so if I wanted to use only 1 ADS1115, I could just use his code as stock, which is this:
// In this example we will use an ADS1115 breakout board instead of the Arduino's local analog inputs
// This is especially useful for nodemcu/esp8266 users who only have a single analog input
#include <Wire.h>
#include <Adafruit_ADS1015.h>
// EmonLibrary examples openenergymonitor.org, Licence GNU GPL V3
#include <EmonLib_I2C.h> // Include Emon Library
EnergyMonitor emon1; // Create an instance
Adafruit_ADS1115 ads; // Create an instance of the ADS1115 object
// Make a callback method for reading the pin value from the ADS instance
int ads1115PinReader(int _pin){
return ads.readADC_SingleEnded(_pin);
}
void setup()
{
emon1.inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
emon1.current(1, 111.1); // Current: input pin, calibration.
}
void loop()
{
double Irms = emon1.calcIrms(1480); // Calculate Irms only
Serial.print(Irms*230.0); // Apparent power
Serial.print(" ");
Serial.println(Irms); // Irms
}
This compiles just fine. Though I am kinda confused as to how to select the "pin" of the ADS.
In the emonlib.cpp he added this code:
//--------------------------------------------------------------------------------------
// Constructor. Set the pinReader to the default pin reader method
//--------------------------------------------------------------------------------------
EnergyMonitor::EnergyMonitor()
{
this->inputPinReader = defaultInputPinReader;
}
//--------------------------------------------------------------------------------------
// By default we just call Arduino's analogRead
//--------------------------------------------------------------------------------------
int EnergyMonitor::defaultInputPinReader(int _pin)
{
return analogRead(_pin);
}
And changed this:
startV = analogRead(inPinV);
to:
startV = (this->inputPinReader)(inPinV);
and a few other spots where he made the adjustment using "this->".
And in the emonlib.h he added this to the Public section:
EnergyMonitor();
typedef int (*inputPinReaderMethod) (int _pin);
inputPinReaderMethod inputPinReader;
static int defaultInputPinReader(int _pin);
Now, for a single ADS1115, I think this works. At least the code compiles. But I need to use 4 ADS1115's as I'll need to be able to monitor up to 16 circuits. I can't for the life of me figure out how to add an array of ADS's to an array of emonlib's.
I tried doing this:
EnergyMonitor emon1[4]; // Create an instance
Adafruit_ADS1115 ads[4]; // Create an instance of the ADS1115 object
// Make a callback method for reading the pin value from the ADS instance
int ads1115PinReader(int _channel, int _pin){
return ads[1].readADC_SingleEnded(_pin);
}
void setup()
{
emon1[1].inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
emon1[1].current(1, 111.1); // Current: input pin, calibration.
}
void loop()
{
double Irms = emon1[1].calcIrms(1480); // Calculate Irms only
Serial.print(Irms*230.0); // Apparent power
Serial.print(" ");
Serial.println(Irms); // Irms
}
but then I get this error:
Emon_ADS_Test:18:27: error: invalid conversion from 'int (*)(int, int)' to 'EnergyMonitor::inputPinReaderMethod {aka int (*)(int)}' [-fpermissive]
emon1[1].inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
I'm not very advanced in coding, and function pointers just confuse the heck outta me.
So my dilemma is I have several ADS1115's I need to match to the several instances of the EmonLib.
There has to be a separate instance for each wire monitored. On my working model that uses an Arduino Nano I have 2 emonlib variables (emon1, emon2). This works fine as it uses the internal ADC, tho I've found out over time that it is not very accurate and not fast enough or high enough resolution for my needs. (ie. when 0-current is flowing, it shows 50W usage).
What do I need to make a change to make this thing work?
Kori
[UPDATE 1]
Ok, after some testing, I do still get this:
emon[i * j].inputPinReader = ads1115PinReader;
emon[i * j].current(j++, 111.1);
Unfortunately this throws an error still:
Emon_ADS_Test:21:33: error: invalid conversion from 'int (*)(int, int)' to 'EnergyMonitor::inputPinReaderMethod {aka int (*)(int)}' [-fpermissive]
emon1[i * j].inputPinReader = ads1115PinReader;
However, it comes to the function pointer as being a problem.
I use this code:
int ads1115PinReader(int _pin){
return ads.readADC_SingleEnded(_pin);
}
It works just fine. However if I do this:
int ads1115PinReader(int _channel, int _pin){
return ads[_channel].readADC_SingleEnded(_pin);
}
I get the error above. In the EmonLib_I2C library, the only thing I can think of is in this part:
typedef int (*inputPinReaderMethod) (int _pin);
inputPinReaderMethod inputPinReader;
static int defaultInputPinReader(int _pin);
not matching up. But even that doesn't make sense. In this line:
emon.inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
does that mean that when I call inputPinReader, it "actually" grabs the value from ads1115PinReader instead of the one in the library?

std::lock_guard (mutex) produces deadlock

First: Thanks for reading this question and tryin' to help me out. I'm new to the whole threading topic and I'm facing a serious mutex deadlock bug right now.
Short introduction:
I wrote a game engine a few months ago, which works perfectly and is being used in games already. This engine is based on SDL2. I wanted to improve my code by making it thread safe, which would be very useful to increase performance or to play around with some other theoretical concepts.
The problem:
The game uses internal game stages to display different states of a game, like displaying the menu, or displaying other parts of the game. When entering the "Asteroid Game"-stage I recieve an exception, which is thrown by the std::lock_guard constructor call.
The problem in detail:
When entering the "Asteroid Game"-stage a modelGetDirection() function is being called to recieve a direction vector of a model. This function uses a lock_guard to make this function being thread safe. When debugging this code section this is where the exception is thrown. The program would enter this lock_guard constructor and would throw an exception. The odd thing is, that this function is NEVER being called before. This is the first time this function is being called and every test run would crash right here!
this is where the debugger would stop in threadx:
inline int _Mtx_lockX(_Mtx_t _Mtx)
{ // throw exception on failure
return (_Check_C_return(_Mtx_lock(_Mtx)));
}
And here are the actual code snippets which I think are important:
mutex struct:
struct LEMutexModel
{
// of course there are more mutexes inside here
mutex modelGetDirection;
};
engine class:
typedef class LEMoon
{
private:
LEMutexModel mtxModel;
// other mutexes, attributes, methods and so on
public:
glm::vec2 modelGetDirection(uint32_t, uint32_t);
// other methods
} *LEMoonInstance;
modelGetDirection() (engine)function definition:
glm::vec2 LEMoon::modelGetDirection(uint32_t id, uint32_t idDirection)
{
lock_guard<mutex> lockA(this->mtxModel.modelGetDirection);
glm::vec2 direction = {0.0f, 0.0f};
LEModel * pElem = this->modelGet(id);
if(pElem == nullptr)
{pElem = this->modelGetFromBuffer(id);}
if(pElem != nullptr)
{direction = pElem->pModel->mdlGetDirection(idDirection);}
else
{
#ifdef LE_DEBUG
char * pErrorString = new char[256 + 1];
sprintf(pErrorString, "LEMoon::modelGetDirection(%u)\n\n", id);
this->printErrorDialog(LE_MDL_NOEXIST, pErrorString);
delete [] pErrorString;
#endif
}
return direction;
}
this is the game function that uses the modelGetDirection method! This function would control a space ship:
void Game::level1ControlShip(void * pointer, bool controlAble)
{
Parameter param = (Parameter) pointer;
static glm::vec2 currentSpeedLeft = {0.0f, 0.0f};
glm::vec2 speedLeft = param->engine->modelGetDirection(MODEL_VERA, LEFT);
static const double INCREASE_SPEED_LEFT = (1.0f / VERA_INCREASE_LEFT) * speedLeft.x * (-1.0f);
// ... more code, I think that's not important
}
So as mentioned before: When entering the level1ControlShip() function, the programm will enter the modelGetDirection() function. When entering the modelGetDirection() function an exception will be thrown when tryin' to call:
lock_guard<mutex> lockA(this->mtxModel.modelGetDirection);
And as mentioned, this is the first call of this function in the whole application run!
So why is that? I appreciate any help here! The whole engine (not the game) is an open source project and can be found on gitHub in case I forgot some important code snippets (sorry! in that case):
GitHub: Lynar Moon Engine
Thanks for your help!
Greetings,
Patrick

Remove chars from one string which are present in another string

this is the code to remove the characters from one string, say p, which are there in the other string, say s, and finally concatenate the two strings and print the final string.
for ex: if inputs are
stringP= "Hello"
StringS= "fellow"
output: Hfellow
another EX
input
stringP= "Android"
StringS= "Google"
output
AndridGoogle
the comparison of the characters is case sensitive.
Currently i am getting segmentation fault after entering the first string. Can anyone please help me in correcting this code? and also why segmentation fault occurs, in which scenarios it occurs?
Thanks in advance.
#include <stdio.h>
#include<string.h>
void remove_char(int *len, char *string1);
int main()
{
char *p,*s,*t;
int len1,len2,i,j;
printf("enter the two strings\n");
scanf("%s",p);
scanf("%s",s);
len1=strlen(p);
len2=strlen(s);
for(i=0;i<len1;i++)
{
for(j=0;j<len2;j++)
{
if(*p==*(s+j))
{
remove_char(&len1,p);
}
if(*p=='\0'||*(s+j)=='\0')
{
break;
}
}
p++;
}
strcat(p,s);
strcat(t,p);
printf("%s",t);
return 0;
}
void remove_char(int *len, char* string1)
{
int a;
for(a=0;a<*len;a++)
{
*string1=*(string1+1);
string1++;
}
len--;
}
The declaration char* p says that p is a variable that contains the address of a character (or potentially the address of a character array).
In your code, you do create storage space for the character (or the array). Think of it this was, p is an alias for a location in the local stack frame (say a four-byte area), and it's contents are interpreted as an address in the heap.
Now, no where in your code to you actually allocate memory, to do this you would need to do something like this:
p = malloc(15*sizeof(char));
This is assuming that you want the user to enter a string of no more than 14 characters (don't forget the null-terminator). Now p contains the address of an area on the heap that can be used to store characters.
So, to answer your question, you are getting a segmentation fault after entering the first string because you failed to allocate memory to store the string in.
Also, note that scanf is insecure in that it will take a string as long as the user feels like typing in and this could result in heap-based buffer overflow. If you want to read in a string of at most 14 character, try this;
#define STR_LEN 14
char* p = malloc(STR_LEN*sizeof(char));
scanf("%STR_LENs", p);
Notice that I have put a length in the specifier so that scanf will limit itself to reading in at most STR_LEN characters. This will help prevent over-flows, not entirely prevent it.

Page fault with newlib functions

I've been porting newlib to my very small kernel, and I'm stumped: whenever I include a function that references a system call, my program will page fault on execution. If I call a function that does not reference a system call, like rand(), nothing will go wrong.
Note: By include, I mean as long as the function, e.g. printf() or fopen(), is somewhere inside the program, even if it isn't called through main().
I've had this problem for quite some time now, and have no idea what could be causing this:
I've rebuilt newlib numerous times
Modified my ELF loader to load the
code from the section headers instead of program headers
Attempted to build newlib/libgloss separately (which failed)
Linked the libraries (libc, libnosys) through the ld script using GROUP, gcc and ld
I'm not quite sure what other information I should include with this, but I'd be happy to include what I can.
Edit: To verify, the page faults occurring are not at the addresses of the failing functions; they are elsewhere in the program. For example, when I call fopen(), located at 0x08048170, I will page fault at 0xA00A316C.
Edit 2:
Relevant code for loading ELF:
int krun(u8int *name) {
int fd = kopen(name);
Elf32_Ehdr *ehdr = kmalloc(sizeof(Elf32_Ehdr*));
read(fd, ehdr, sizeof(Elf32_Ehdr));
if (ehdr->e_ident[0] != 0x7F || ehdr->e_ident[1] != 'E' || ehdr->e_ident[2] != 'L' || ehdr->e_ident[3] != 'F') {
kfree(ehdr);
return -1;
}
int pheaders = ehdr->e_phnum;
int phoff = ehdr->e_phoff;
int phsize = ehdr->e_phentsize;
int sheaders = ehdr->e_shnum;
int shoff = ehdr->e_shoff;
int shsize = ehdr->e_shentsize;
for (int i = 0; i < pheaders; i++) {
lseek(fd, phoff + phsize * i, SEEK_SET);
Elf32_Phdr *phdr = kmalloc(sizeof(Elf32_Phdr*));
read(fd, phdr, sizeof(Elf32_Phdr));
u32int page = PMMAllocPage();
int flags = 0;
if (phdr->p_flags & PF_R) flags |= PAGE_PRESENT;
if (phdr->p_flags & PF_W) flags |= PAGE_WRITE;
int pages = (phdr->p_memsz / 0x1000) + 1;
while (pages >= 0) {
u32int mapaddr = (phdr->p_vaddr + (pages * 0x1000)) & 0xFFFFF000;
map(mapaddr, page, flags | PAGE_USER);
pages--;
}
lseek(fd, phdr->p_offset, SEEK_SET);
read(fd, (void *)phdr->p_vaddr, phdr->p_filesz);
kfree(phdr);
}
// Removed: code block that zeroes .bss: it's already zeroed whenever I check it anyways
// Removed: code block that creates thread and adds it to scheduler
kfree(ehdr);
return 0;
}
Edit 3: I've noticed that if I call a system call, such as write(), and then call printf() two or more times, I will get an unknown opcode interrupt. Odd.
Whoops! Figured it out: when I map the virtual address, I should allocate a new page each time, like so:
map(mapaddr, PMMAllocPage(), flags | PAGE_USER);
Now it works fine.
For those curious as to why it didn't work: when I wasn't including printf(), the size of the program was under 0x1000 bytes, so mapping with only one page was okay. When I include printf() or fopen(), the size of the program was much bigger so that's what caused the issue.