因此,我的任务是在C中创建一个汇编器。因此,我的大部分工作都在进行,但是第一部分是扫描汇编文件并查找标签,并为每个标签分配正确的“程序计数器”位置。一切工作都很好,除非在底部有一个标签,在其下面有一个空白行,并在其后有一个.end指令。我尝试打印每一行以查看其正在读取的内容,似乎它正在读取最后一个标签两次,因此对于同一标签它两次将程序计数器加1,而对于该标签来说这是不正确的,而且我似乎无法找出问题所在。任何帮助表示赞赏。此时,除了增加lc之外,我没有为每个命令添加任何逻辑,因为这是完成这部分atm所需要做的全部工作。
int firstPass(FILE *infile, int labels[], int lc)
{
char line[LINE_SIZE] = {};
int lineCount = 0;
int done = 0;
int endFound = -1;
char c;
rewind(infile);
while (fscanf(infile, "%[^\n]", line) != EOF && lineCount < LIMIT && !done)
{
lineCount++;
fscanf(infile, "%c", &c);
removeSpaces(line);
toUpperCase(line);
if (line[0] != 0 && line[0] != ';')
{
if (!strncmp(line, ".END", 4))
{
done = 1;
endFound = 0;
}
else if(!strncmp(line, "LDR", 3))
{
lc++;
}
else if(!strncmp(line, "LD", 2))
{
lc++;
}
else if(!strncmp(line, "ADD", 3))
{
lc++;
}
else if(!strncmp(line, "AND", 3))
{
lc++;
}
else if(!strncmp(line, "NOT", 3))
{
lc++;
}
else if(!strncmp(line, "STR", 3))
{
lc++;
}
else if(!strncmp(line, "ST", 2))
{
lc++;
}
else if(!strncmp(line, "BR", 2))
{
lc++;
}
else if(!strncmp(line, "TRAP", 4))
{
lc++;
}
else if (line[0] == 'L' && line[1] >= '0' && line[1] <= '9')
{
if (line[2] == '.')
{
labels[line[1] - '0'] = lc;
lc++;
}
else
{
labels[line[1] - '0'] = lc;
}
}
}
}
if (endFound == -1)
{
printf("ERROR 4: Missing end directive.\n");
}
return endFound;
}
这是我正在使用的测试文件。
;Test file for assembly
;This is a comment
.orig x3000
ADD R1, R2, R3
add R0, R3, #10
and R1, R1, R2
AND R0, R3, #-10
L0
BR L1
BRN L0
BRZ L1
BRP L0
BRNZ L1
BRNP L0
BRZP L1
BRNZP L0
LD R1, L2
LDR R1, R2, #-5
L1
NOT R3, R4
ST R5, L2
STR R6, R1, #-5
TRAP x20
TRAP x21
TRAP x22
TRAP x23
TRAP x24
TRAP x25
L2 .FILL 0
L3 .FILL 0
L4 .FILL 0
.END
每当我将标签打印到控制台时,它都会打印
L0
L1
L2 .FILL 0
L3 .FILL 0
L4 .FILL 0
L4 .FILL 0
我似乎无法弄清为什么它似乎两次读取L4。
答案 0 :(得分:4)
fscanf
主要返回成功读入的项目数。如果您有一个空行(即只有一个新行),那么fscanf(infile, "%[^\n]", line)
将不会读入任何内容到line
中,并且line
保持不变(即文件中前一行的值)。
要解决此问题,请更准确地检查fscanf
的返回值:
int fscanfResult;
while ((fscanfResult=fscanf(infile, "%[^\n]", line) != EOF && ...) {
if (fscanfResult == 0) {
fgets(line,infile); // take the new line out of the buffer.
continue;
}
...
通常,我倾向于使用fgets
阅读完整的行,然后进行解析。 fscanf
在使用它来扫描基于行的输入时有很多陷阱。
如果必须保持while
部分不变,那么检测空行的另一种方法是在下一个fscanf
之前重置缓冲区:
while (fscanf(infile, "%[^\n]", line) != EOF && lineCount < LIMIT && !done) {
if (!line[0]) { // nothing read in?
fgets(line,infile); // take the new line out of the buffer.
continue;
}
....
// all your logic goes here
....
line[0] = '\0'; // clear the buffer; if fscanf then does not read in anything, line remains empty.
}