Hello all,

I turn once again to the wisdom of the internet:

I have attached my two files to this post as to not use up a whole lot of space. The program is a mock "assembler" it takes mock assembly code and turns it into a file with hex values that represent the commands.

What I have compiles fine, but when I try to run it against the input.s file attached I get a segfault. Running the program through valgrind, I get 8 entries of "Conditional jump or move depends on uninitialised value(s)" but each say that the "Uninitialised value was created by a stack allocation" so I don't think that there is anything that I can do.

Can someone take a look at my code and tell me where I went wrong?

Many thanks,
~xcr

Edited 6 Years Ago by xcr: n/a

Attachments
#This program gets two single digit numbers, A and B, from the user
#Then prints out the numbers A through B
LOADI A 1 #This is a comment
LOADI B 48 #This is another comment
IN C 0
SUB D C B #This is a third comment
IN C 0
SUB E C B #Yet another comment
#Starting value in D, ending value is E
LTE D E
NOT
CJMP
ADD C D B #still commenting for shits and giggles
OUT C 15
ADD D D A #one more for good measure
JMP
HLT
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sas_include.h"
#define MAX_BUFFER 200

int main(int argc, char * argv[]) {
    FILE * infile;
    FILE * outfile;
    char *line = '\0';
    char *instr = '\0';
    int arg0;
    int arg1;
    int arg2;

/*usage check*/
    if (argc != 3) {
	printf( "Usage: sas input.s output.o\n");
	return 1;
    }else{
	/*read infile & open outfile*/
	infile = fopen(argv[1],"r");
	outfile = fopen(argv[2],"w");
	while (fgets(line, MAX_BUFFER, infile) != NULL){
	    *(strchr(line,'#')) = '\0';
	    switch (sscanf(line, "%s %i %i %i", instr, &arg0, &arg1, &arg2)){
		case 0: 
		    break; /*comment line*/
		case 1:
		    if ( strcmp(instr,"HLT") || strcmp(instr,"hlt")) 
			fprintf(outfile,"0x%X\n",HALT_OP);
		    if ( strcmp(instr,"NOP") || strcmp(instr,"nop")) 
			fprintf(outfile,"0x%X\n",(NOP_OP<<28));
		    if ( strcmp(instr,"NOT") || strcmp(instr,"not")) 
			fprintf(outfile,"0x%X\n",(NOT_OP<<28));
		    break; /*halt, no_op, not*/
		case 2:
		    if ( strcmp(instr,"JMP") || strcmp(instr,"jmp")) 
			fprintf(outfile,"0x%X\n",JUMP(arg0));
		    if ( strcmp(instr,"CJMP") || strcmp(instr,"cjmp")) 
			fprintf(outfile,"0x%X\n",CJUMP(arg0));
		    if ( strcmp(instr,"OJMP") || strcmp(instr,"ojmp")) 
			fprintf(outfile,"0x%X\n",OJUMP(arg0));
		    break; /*Jump, cjump, ojump*/
		case 3:
		    if ( strcmp(instr,"LOAD") || strcmp(instr,"load")) 
			fprintf(outfile,"0x%X\n",LOAD(arg0,arg1));
		    if ( strcmp(instr,"STORE") || strcmp(instr,"store")) 
			fprintf(outfile,"0x%X\n",STORE(arg0,arg1));
		    if ( strcmp(instr,"LOADI") || strcmp(instr,"loadi")) 
			fprintf(outfile,"0x%X\n",LOADI(arg0,arg1));
		    if ( strcmp(instr,"IN") || strcmp(instr,"in")) 
			fprintf(outfile,"0x%X\n",IN(arg0,arg1));
		    if ( strcmp(instr,"OUT") || strcmp(instr,"out")) 
			fprintf(outfile,"0x%X\n",OUT(arg0,arg1));
		    if ( strcmp(instr,"EQU") || strcmp(instr,"equ")) 
			fprintf(outfile,"0x%X\n",EQU(arg0,arg1));
		    if ( strcmp(instr,"LT") || strcmp(instr,"lt")) 
			fprintf(outfile,"0x%X\n",LT(arg0,arg1));
		    if ( strcmp(instr,"LTE") || strcmp(instr,"lte")) 
			fprintf(outfile,"0x%X\n",LTE(arg0,arg1));
		    break;/*Load, store, loadI, In, Out, Equ, lt, lte*/
		case 4:
		    if ( strcmp(instr,"ADD") || strcmp(instr,"add")) 
			fprintf(outfile,"0x%X\n",ADD(arg0,arg1,arg2));
		    if ( strcmp(instr,"SUB") || strcmp(instr,"sub")) 
			fprintf(outfile,"0x%X\n",SUB(arg0,arg1,arg2));
		    break; /*Add, sub*/
		default: 
		    break;
	    } /*switch*/
	}/*while*/
	fclose(infile);
	fclose(outfile);
    }/*if/esle*/

    return 0; 
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*macro definitions*/

 /*operations*/
#define JUMP(addr) ( (JUMP_OP<<28) | (addr) )
#define CJUMP(addr) ( (CJUMP_OP<<28) | (addr) )
#define OJUMP(addr) ( (OJUMP_OP<<28) | (addr) )
#define LOAD(dest,addr) ( (LOAD_OP<<28) | ((dest)<<24) | (addr) )
#define STORE(dest,addr) ( (STORE_OP<<28) | ((dest)<<24) | (addr) )
#define LOADI(dest,val) ( (LOADI_OP<<28) | ((dest)<<24) | (val) )
#define ADD(dest,arg1,arg2) ( (ADD_OP<<28) | ((dest)<<24) | ((arg1)<<20) | ((arg2)<<16) )
#define SUB(dest,arg1,arg2) ( (SUB_OP<<28) | ((dest)<<24) | ((arg1)<<20) | ((arg2)<<16) )
#define IN(dest,port) ( (IN_OP<<28) | ((dest)<<24) | (port) )
#define OUT(dest,port) ( (OUT_OP<<28) | ((dest)<<24) | (port) )
#define EQU(reg1,reg2) ( (EQU_OP<<28) | ((reg1)<<24) | ((reg2)<<20) )
#define LT(reg1,reg2) ( (LTE_OP<<28) | ((reg1)<<24) | ((reg2)<<20) )
#define LTE(reg1,reg2) ( (LTE_OP<<28) | ((reg1)<<24) | ((reg2)<<20) )

 /*OP codes*/
#define HALT_OP 0000
#define JUMP_OP 0001
#define CJUMP_OP 0010
#define OJUMP_OP 0011
#define LOAD_OP 0100
#define STORE_OP 0101
#define LOADI_OP 0110
#define NOP_OP 0111
#define ADD_OP 1000
#define SUB_OP 1001
#define IN_OP 1010
#define OUT_OP 1011
#define EQU_OP 1100
#define LT_OP 1101
#define LTE_OP 1110
#define NOT_OP 1111

>>while (fgets(line, MAX_BUFFER, infile) != NULL){

line is a NULL pointer. You must allocate memory for it before you can use it here.
Add this somewhere before that loop line = malloc(MAX_BUFFER);

Edited 6 Years Ago by Ancient Dragon: n/a

Thank you for your reply, I mad the change that you suggested, but now I am having the problem that the fprintf statements don't write anything to the output file. I have modified my code with a bunch of printfs to try and debug, and what I see is that the operations enter the switch statment and sscanf returns that it didn't scan any fields in.

I did modify the format of the input files to be tab delimited and modified the sscanf for tabs.

I am completely baffled as to why sscanf returns 0 for each and every line.

My modified code is attached.

Attachments
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sas_include.h"
#define MAX_BUFFER 200

int main(int argc, char * argv[]) {
    FILE * infile;
    FILE * outfile;
    char *line = malloc(MAX_BUFFER*sizeof(char));
    char *instr = '\0';
    int arg0;
    int arg1;
    int arg2;
    char *op0 = '\0';
    char *op1 = '\0';
    char *op2 = '\0';

/*usage check*/
    if (argc != 3) {
	printf( "Usage: sas input.s output.o\n");
	return 1;
    }else{
	/*read infile & open outfile*/
	infile = fopen(argv[1],"rw");
	outfile = fopen(argv[2],"a+");
	while (fgets(line, MAX_BUFFER, infile) != NULL){
	    char * check = strchr(line,'#');
	    if ( NULL != check )
		*check = '\0';
	    switch (sscanf(line, "%s\t%s\t%s\t%s", instr, op0, op1, op2)){
		case 0: 
		    break; /*comment line*/
		case 1:
		    if ( strcmp(instr,"HLT") || strcmp(instr,"hlt")) 
			fprintf(outfile,"0x%X\n",HALT_OP);
		    if ( strcmp(instr,"NOP") || strcmp(instr,"nop")) 
			fprintf(outfile,"0x%X\n",(NOP_OP<<28));
		    if ( strcmp(instr,"NOT") || strcmp(instr,"not")) 
			fprintf(outfile,"0x%X\n",(NOT_OP<<28));
		    break; /*halt, no_op, not*/
		case 2:
		    arg0 = change_fn(op0);
		    if ( strcmp(instr,"JMP") || strcmp(instr,"jmp")) 
			fprintf(outfile,"0x%X\n",JUMP(arg0));
		    if ( strcmp(instr,"CJMP") || strcmp(instr,"cjmp")) 
			fprintf(outfile,"0x%X\n",CJUMP(arg0));
		    if ( strcmp(instr,"OJMP") || strcmp(instr,"ojmp")) 
			fprintf(outfile,"0x%X\n",OJUMP(arg0));
		    break; /*Jump, cjump, ojump*/
		case 3:
		    arg0 = change_fn(op0);
		    arg1 = change_fn(op1);
		    if ( strcmp(instr,"LOAD") || strcmp(instr,"load")) 
			fprintf(outfile,"0x%X\n",LOAD(arg0,arg1));
		    if ( strcmp(instr,"STORE") || strcmp(instr,"store")) 
			fprintf(outfile,"0x%X\n",STORE(arg0,arg1));
		    if ( strcmp(instr,"LOADI") || strcmp(instr,"loadi")) 
			fprintf(outfile,"0x%X\n",LOADI(arg0,arg1));
		    if ( strcmp(instr,"IN") || strcmp(instr,"in")) 
			fprintf(outfile,"0x%X\n",IN(arg0,arg1));
		    if ( strcmp(instr,"OUT") || strcmp(instr,"out")) 
			fprintf(outfile,"0x%X\n",OUT(arg0,arg1));
		    if ( strcmp(instr,"EQU") || strcmp(instr,"equ")) 
			fprintf(outfile,"0x%X\n",EQU(arg0,arg1));
		    if ( strcmp(instr,"LT") || strcmp(instr,"lt")) 
			fprintf(outfile,"0x%X\n",LT(arg0,arg1));
		    if ( strcmp(instr,"LTE") || strcmp(instr,"lte")) 
			fprintf(outfile,"0x%X\n",LTE(arg0,arg1));
		    break;/*Load, store, loadI, In, Out, Equ, lt, lte*/
		case 4:
		    arg0 = change_fn(op0);
		    arg1 = change_fn(op1);
		    arg2 = change_fn(op2);
		    if ( strcmp(instr,"ADD") || strcmp(instr,"add")) 
			fprintf(outfile,"0x%X\n",ADD(arg0,arg1,arg2));
		    if ( strcmp(instr,"SUB") || strcmp(instr,"sub")) 
			fprintf(outfile,"0x%X\n",SUB(arg0,arg1,arg2));
		    break; /*Add, sub*/
		default: 
		    break;
	    } /*switch*/ 
	}/*while*/
	fclose(infile);
	fclose(outfile);
    }/*if/esle*/

    return 0; 
}

You have the same problem with other char* variables that you had with line. Just how do you expect sscanf() to work if those are unallocated buffers? sscanf() doesn't allocate the memory, that is your responsibility.

You need to proofread your who program very carefully and make all corrections like that.

This article has been dead for over six months. Start a new discussion instead.