Search code examples
cfor-loopx86-64osdevfunction-definition

Error passing by reference when making os


I am making an os and have booted into a 64 bit kernel made in c. I have made a print function which is working and am trying to make a function to convert hex values to string so I can print them. My code is causing boot loops, yet when I compile the exact same code to run normally in linux it works perfectly. The relevant code:

int logarithm(double value, int base, int* output) {
    int i = 0;

    while (value > 1) {
        value /= base;
        i++;
    }

    *output = i;
}

int power(int value, int power, int* output) {
    if (power == 0) {
        value = 1;
    } else {
        for (int i = 0; i < (power - 1); i++) {
            value *= value;
        }
    }

    *output = value;
}

void hexToStr(unsigned int hex, char** string) {
    int hexLength = 0;
    logarithm((double)hex, 16, &hexLength);
    char output[hexLength];
    output[hexLength] = 0;

    int powerValue = 0;
    for (int i = 0; i < hexLength; i++) {
        power(16, i, &powerValue);
        output[hexLength - i - 1] = (hex & (powerValue * 15)) / powerValue + '0';
    }

    *string = output;
}

If I change the hexToStr() function code to this (removing the need for logarithm() and power() functions by hardcoding values for the string), it works in both linux and my kernel:

void hexToStr(unsigned int hex, char** string) {
    int hexLength = 10;
    char output[hexLength];
    output[hexLength] = 0;

    int powerValue = 0;
    for (int i = 0; i < hexLength; i++) {
        output[hexLength - i - 1] = 'A';
    }

    *string = output;
}

Any suggestions as to why this would happen?


Solution

  • Needed to enable SSE unit to work with floats and doubles. As well as change how values are passed back. Working code:

    void log(float value, float base, uint64_t* output) {
        uint64_t i = 0;
    
        while (value >= 1) {
            value /= base;
            i++;
        }
    
        *output = i;
    }
    
    void pow(uint64_t value, uint64_t exponent, uint64_t* output) {
        uint64_t result = 1;
    
        for (uint64_t i = 0; i < exponent; i++) {
            result = result * value;
        }
    
        *output = result;
    }
    
    void hexToStr(uint64_t hex, char* output) {
        uint8_t hexLen = 16;
        log((float)hex, (float)16, &hexLen);
        char result[hexLen + 3];
        result[0] = '0';
        result[1] = 'x';
        result[hexLen + 2] = 0;
    
        uint64_t powerValue = 1;
        for (uint8_t i = 0; i < hexLen; i++) {
            pow(16, i, &powerValue);
            result[hexLen - i + 1] = (hex & (uint64_t)(powerValue * (uint64_t)15)) / powerValue + '0';
        }
    
        for (uint8_t i = 0; i < hexLen + 3; i++) {
            switch(result[i]) {
                case ':':
                    result[i] = 'A';
                    break;
                case ';':
                    result[i] = 'B';
                    break;
                case '<':
                    result[i] = 'C';
                    break;
                case '=':
                    result[i] = 'D';
                    break;
                case '>':
                    result[i] = 'E';
                    break;
                case '?':
                    result[i] = 'F';
                    break;
            }
            output[i] = result[i];
        }
    }